Spring Boot - 将AWS中的文件从一个服务移动到另一个服务

问题描述:

我有2个服务A和B,并且用户可以请求A下载文件。为此,服务A呼叫B请求文件,获取它并以下载的形式向用户发送响应。Spring Boot - 将AWS中的文件从一个服务移动到另一个服务

我试图做到这一点的方式是,服务B在控制器中获得正确的调用。然后它从AWS获取File对象,并从中创建一个FileSystemResource,返回ResponseEntity<FileSystemResource>

我的问题是,当A收到响应,其正文为空。下载仍然发生,但我得到一个空文件(零字节)。任何想法我做错了什么?这可能吗?

我的服务控制器A

@GetMapping(value = "/get") 
public ResponseEntity<FileSystemResource> downloadDocument(
     HttpServletRequest httpServletRequest, 
     HttpServletResponse httpServletResponse 
) { 
    httpServletResponse.setHeader(
      "Content-Disposition", 
      "attachment; filename=" + filename); 

    httpServletResponse.setHeader(
      "Content-Type", 
      "application/octet-stream" 
    ); 

    return ResponseEntity.ok(
      documentsService.getDocumentToDownload(fileName)); 
} 

我的服务B

@GetMapping(value = "/get") 
public ResponseEntity<FileSystemResource> downloadDocument(
     @RequestParam(value = "fileName") String fileName, 
     HttpServletResponse httpServletResponse 
) { 
    File doc = documentsService.getFileForDocumentInS3(
      fileName); 

    return ResponseEntity.ok(
      new FileSystemResource(doc.getAbsolutePath()) 
    ); 
} 

控制器这是我的服务与AWS互动确实(在服务B)。请注意,我的aws3Client变量是一个包含传输管理器的包装器。与AWS的连接性好。

public File getFileForDocumentInS3(
     String bucketName, 
     String fileKey 
) { 
    try { 
     File toReturn = File.createTempFile(fileKey, ".tmp"); 
     toReturn.deleteOnExit(); 

     GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, fileKey); 

     awsS3Client.getTransferManager().download(getObjectRequest, toReturn); 

     return toReturn; 
    } catch (Exception ex) { 
     //catching exception here 
    } 
} 
+0

你在serviceB.downloadDocument看到文件大小()或者在这些方法返回任何东西之前在getFileForDocumentInS3()方法中。 –

+2

只是一个建议:不要在多个服务之间传递文件,而是使用[Signed S3 URLs](http://docs.aws.amazon.com/AmazonS3/latest/dev/ShareObjectPreSignedURLJavaSDK.html)并将其传递给客户端他们可以直接下载文件。自从文件直接下载一次后,性能更好,带宽更少。 –

+0

@AmitKBist是的,他们确实返回一个可以与调试器一起看到的文件,并且看到它指向在我的计算机上创建的临时文件。如果我打开文件在控制台中查看其内容,我会看到数据。 –

您在选择发送服务之间的文件,因为你不能产生在一个版本桶的特定版本签署网址的评论中提到。

由于SDK版本1.11.123(当前最新的1.11.186),你可以设置一个标识的URL的版本ID与GeneratedPresignedUrlRequest.withVersionId这样的:

final URL url = s3.generatePresignedUrl(
     new GeneratePresignedUrlRequest("my-bucket", "my-key", HttpMethod.GET) 
      .withVersionId("version-id") 
); 
+1

是的,你是对的。我使用的是旧版AWS,并没有在线检查API ...我更新到新版本并获得了排序。 由于您是唯一发布了答案的人,我会将其标记为有效答案;) –

+0

我在发布了您在评论中发现的答案后看到了。在这些情况下,您可以回答自己的问题,并接受该答案以帮助未来的其他人 – Raniz