繁体   English   中英

如何从 rest controller java 重定向 s3 链接

[英]How to redirect s3 link from rest controller java

我们有 S3 存储,有很多文件,jpg,mp3 和其他我需要做什么? 我需要重定向客户端以从我们的 s3 获取文件而不将其上传到我们的服务器上,我希望该客户在他的 PC 上获取具有名称和扩展名的文件

所以看起来客户向我们发送 uuid - 我们在 s3 上找到此文件的链接并像这样重定向它

  @GetMapping("/test/{uuid}")
  public ResponseEntity<Void> getFile(@PathVariable UUID uuid) {
    var url = storageServiceS3.getUrl(uuid);
    try {
      var name = storageServiceS3.getName(uuid);
      return ResponseEntity.status(HttpStatus.MOVED_PERMANENTLY)
        .header(HttpHeaders.LOCATION, url)
        .header(HttpHeaders.CONTENT_TYPE, new MimetypesFileTypeMap().getContentType(name))
        .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + name)
        .build();
    } catch (NoSuchKeyException ex) {
      return ResponseEntity.status(HttpStatus.NOT_FOUND)
        .build();
    }
  }

一切正常,文件正在下载,但有一个问题 - 文件没有名称(它的名称仍然是 s3 的键)并且没有扩展名。

我认为这段代码不能正常工作

.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + name)

有什么办法可以做到这一点,还是我仍然需要将文件上传到服务器然后发送到客户端?

@Алексеев станислав

一些解决方法是通过 javascript 使用您的 rest 服务,并在客户端下载时在新的 header 响应和重命名文件中添加文件名。

// don't forget to allow X-File-Name header on CORS in spring
headers.add("X-File-Name",  nameToBeDownloaded );

ANGULAR 上的示例,但可以解析为其他语言

this.http.get(uri_link_spring_redirecting_to_S3, {
    responseType: 'blob',
    observe: 'response'
}).subscribe(
    (response) => {
        var link = document.createElement('a');
        var file = new Blob([response.body], {
            type: 'text/csv;charset=utf-8;'
        });
        link.href = window.URL.createObjectURL(file);
        link.download = response?.headers?.get('X-File-Name');; 'download.csv';
        link.click();
    },
    error => {
        ...
    }
)

最后我找到了解决方案 - 我使用 S3Presigner,制作预签名 url 并用简单的 Http 响应重定向它

  @Bean
  public S3Presigner getS3Presigner() {
    return S3Presigner.builder()
      .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create(ACCESS_KEY, SECRET_KEY)))
      .region(Region.of(REGION))
      .endpointOverride(URI.create(END_POINT))
      .build();
  }

  public String getPresignedURL(UUID uuid) {
    var name = getName(uuid);
    var contentDisposition = "attachment;filename=" + name;
    var contentType = new MimetypesFileTypeMap().getContentType(name);

    GetObjectRequest getObjectRequest = GetObjectRequest.builder()
      .bucket(BUCKET)
      .key(uuid.toString())
      .responseContentDisposition(contentDisposition)
      .responseContentType(contentType)
      .build();

    GetObjectPresignRequest getObjectPresignRequest =
      GetObjectPresignRequest.builder()
        .signatureDuration(Duration.ofMinutes(5))
        .getObjectRequest(getObjectRequest)
        .build();

    PresignedGetObjectRequest presignedGetObjectRequest =
      s3Presigner.presignGetObject(getObjectPresignRequest);

   return presignedGetObjectRequest.url().toString();
  }

@GetMapping("/redirect/{uuid}")
  public void redirectToS3(@PathVariable UUID uuid, HttpServletResponse response) {
    try {
      var URI = storageServiceS3.getPresignedURL(uuid);
      response.sendRedirect(URI);
    } catch (NoSuchKeyException | IOException e) {
      response.setStatus(404);
    }
  }

它工作得很好;)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM