[英]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.