[英]Downloading AWS S3 file as a stream in Spring boot
I want to expose an API to download a S3 bucket file content as stream to its consumers.我想公开一个 API 以将 S3 存储桶文件内容作为 stream 下载给它的消费者。 The API URL is like /downloadfile/** which is GET request.
API URL 就像 /downloadfile/** 是 GET 请求。
Here is the controller pseudo code I wrote till now which is giving me 406 error all the time.这是我到目前为止编写的 controller 伪代码,它一直给我 406 错误。
@GetMapping(value = "/downloadfile/**", produces = { MediaType.APPLICATION_OCTET_STREAM_VALUE })
public ResponseEntity<Object> downloadFile(HttpServletRequest request) {
//reads the content from S3 bucket and returns a S3ObjectInputStream
S3ObjectInputStream object = null;
object = publishAmazonS3.getObject("12345bucket", "/logs/file1.log").getObjectContent();
return object
}
Any suggestions here on the way of doing this and what I am doing wrong?关于这样做的方式以及我做错了什么,这里有什么建议吗?
I was able to download the file as a stream by using StreamingResponseBody
class from Spring.通过使用来自 Spring 的
StreamingResponseBody
class,我能够将文件下载为 stream。
Here is the code I used:这是我使用的代码:
@GetMapping(value = "/downloadfile/**", produces = { MediaType.APPLICATION_OCTET_STREAM_VALUE })
public ResponseEntity<S3ObjectInputStream> downloadFile(HttpServletRequest request) {
//reads the content from S3 bucket and returns a S3ObjectInputStream
S3Object object = publishAmazonS3.getObject("12345bucket", "/logs/file1.log");
S3ObjectInputStream finalObject = object.getObjectContent();
final StreamingResponseBody body = outputStream -> {
int numberOfBytesToWrite = 0;
byte[] data = new byte[1024];
while ((numberOfBytesToWrite = finalObject.read(data, 0, data.length)) != -1) {
System.out.println("Writing some bytes..");
outputStream.write(data, 0, numberOfBytesToWrite);
}
finalObject.close();
};
return new ResponseEntity<>(body, HttpStatus.OK);
}
The way to test the streaming is done correctly or not is to have a file of around 400mb to download.测试流媒体是否正确完成的方法是下载一个大约 400mb 的文件。 Reduce your Xmx to 256mb by passing the in the vm options.
通过传入 vm 选项将 Xmx 减少到 256mb。 Now, compare the download functionality with and without using
StreamingResponseBody
, you will get OutofMemoryError
when using the conventional OutputStreams for writing the content现在,比较使用和不使用
StreamingResponseBody
的下载功能,当使用常规的 OutputStreams 写入内容时,您将得到OutofMemoryError
You can solve with the below example你可以用下面的例子来解决
import java.io.ByteArrayOutputStream;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import com.grokonez.s3.services.S3Services;
@RestController
public class DownloadFileController {
@Autowired
S3Services s3Services;
/*
* Download Files
*/
@GetMapping("/api/file/{keyname}")
public ResponseEntity<byte[]> downloadFile(@PathVariable String keyname) {
ByteArrayOutputStream downloadInputStream = s3Services.downloadFile(keyname);
return ResponseEntity.ok().contentType(contentType(keyname))
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + keyname + "\"")
.body(downloadInputStream.toByteArray());
}
private MediaType contentType(String keyname) {
String[] arr = keyname.split("\\.");
String type = arr[arr.length - 1];
switch (type) {
case "txt":
return MediaType.TEXT_PLAIN;
case "png":
return MediaType.IMAGE_PNG;
case "jpg":
return MediaType.IMAGE_JPEG;
default:
return MediaType.APPLICATION_OCTET_STREAM;
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.