没有记忆保持在春季启动流/下载文件

问题描述 投票:0回答:1

我的应用程序使用谷歌云存储用于存储大文件和Spring引导作为后端。

我刚刚完成实施负责下载控制器,以下是我认为可能是正确的,但我从浏览器中获取的行为是不是我的预期。

步骤

如果我尝试下载一个文件,下面会发生什么:

  1. 该文件(“BLOB”)被从谷歌云存储使用ReadChannel读
  2. 通道写入一个ByteArrayOutputStream;
  3. 通道写入用缓冲器
  4. 所述ByteArrayOutputStream被转换在InputStreamResource这
  5. InputStream的资源,然后在ResponseEntity通过

意外的行为

如果用户去下载的控制,并要求一个特定的文件,该文件是第一个完全装在服务器上,然后提供给客户端。同时,客户看到像服务器“没有响应”(因为服务器加载文件),这是不是很好。当文件被然后完全在服务器上加载的,是要去出现在“已下载”真快。

我想要的东西,是为了避免“没有响应”的一部分,和流或文件给客户端,就像做当您尝试下载一个大文件时,它通常会发生,你在Chrome中看到文件围绕“下载”轮。

任何帮助理解什么是错用下面的代码,将不胜感激!

为Spring控制器的代码如下:

@RequestMapping("/**/*")
    public ResponseEntity<InputStreamResource> downloadFile(
                RedirectAttributes redirectAttributes, HttpServletRequest request, HttpServletResponse response) throws Exception {
                String fid = ....
                WritableByteChannel channel;

                    Storage storage = new DownloadAction().getStorage();
                    BlobId blobId = BlobId.of(BUCKET_ID, blobPath);
                    Blob blob = storage.get(blobId);


                    ByteArrayOutputStream writeTo = new ByteArrayOutputStream();
                    try (ReadChannel reader = blob.reader()) {
                        channel = Channels.newChannel(writeTo);
                        ByteBuffer bytes = ByteBuffer.allocate(64 * 1024);
                        while (reader.read(bytes) > 0) {

                            System.out.println("here");
                            bytes.flip();
                            channel.write(bytes);
                            bytes.clear();
                        }
                    }

                    channel.close();
                    writeTo.close();

                    InputStream tmp = new ByteArrayInputStream(writeTo.toByteArray());
                    InputStreamResource resource = new InputStreamResource(tmp);
                    MediaType mediaType = MediaType.parseMediaType(mimeType);
                    return ResponseEntity.ok()
                            .contentType(mediaType)
                            .contentLength(fileSize)
                            .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + fileName + "\"")
                            .body(resource);
                } catch (IOException e) {
                    return ResponseEntity.notFound().build();
                }
            } catch (Exception e) {
                return ResponseEntity.notFound().build();
            }

    }
java spring spring-boot google-cloud-storage
1个回答
1
投票

根据你的问题,在你的水桶中的对象是专用的,你想给访问它们的人的有限组。如果是这样的 - 签名的URL的是你所需要的。

您可以生成标识的URL的水桶特定对象和重定向用户到生成的URL - 因此他将下载的文件自己。

更多信息:GCloud Signed URLs

© www.soinside.com 2019 - 2024. All rights reserved.