如何解决通过 AWS Java SDK 从 S3 读取文本文件时出错
我正在尝试通过 JAVA SDK v2 从 AWS S3 读取文本文件,并通过 HTTP(使用
com.sun.net.httpserver.HttpServer
)。我想将内容读取为字符串。但是我下面的简单代码不起作用。
有什么问题?如何解决?
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
//...
Region region = Region.US_WEST_2;
String bucketName = "file-store";
S3Client s3Client = S3Client.builder().region(region).build();
//...
class GetFileHandlerV2 implements HttpHandler {
@Override
public void handle(HttpExchange he) throws IOException {
GetobjectRequest getobjectRequest = GetobjectRequest.builder()
.bucket(bucketName)
.key(id + "/files/" + id + ".txt")
.build();
OutputStream os = he.getResponseBody();
s3Client.getobject(getobjectRequest,ResponseTransformer.toOutputStream(os));
os.close();
//...
}
}
以下是错误:
java.io.IOException: response headers not sent yet
at sun.net.httpserver.PlaceholderOutputStream.checkWrap(ExchangeImpl.java:433) ~[jdk.httpserver:?]
at sun.net.httpserver.PlaceholderOutputStream.write(ExchangeImpl.java:448) ~[jdk.httpserver:?]
at java.io.InputStream.transferTo(InputStream.java:772) ~[?:?]
at comcast.labs.objectstore.FileRetriever$GetFileHandlerV2.handle(FileRetriever.java:112) [FileRetriever-1.0.jar:?]
at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:77) [jdk.httpserver:?]
at sun.net.httpserver.AuthFilter.doFilter(AuthFilter.java:82) [jdk.httpserver:?]
at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:80) [jdk.httpserver:?]
at sun.net.httpserver.ServerImpl$Exchange$LinkHandler.handle(ServerImpl.java:692) [jdk.httpserver:?]
at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:77) [jdk.httpserver:?]
at sun.net.httpserver.ServerImpl$Exchange.run(ServerImpl.java:664) [jdk.httpserver:?]
at sun.net.httpserver.ServerImpl$DefaultExecutor.execute(ServerImpl.java:159) [jdk.httpserver:?]
at sun.net.httpserver.ServerImpl$dispatcher.handle(ServerImpl.java:442) [jdk.httpserver:?]
at sun.net.httpserver.ServerImpl$dispatcher.run(ServerImpl.java:408) [jdk.httpserver:?]
at java.lang.Thread.run(Thread.java:835) [?:?]
解决方法
请考虑查看 HttpExchange
documentation。它提供了 HttpExchange
生命周期中的典型步骤序列。
具体来说,它表示在写入响应正文之前,使用OutputStream
返回的getResponseBody
,必须调用方法sendResponseHeaders
才能真正开始向响应发送信息客户端。来自javadoc:
开始使用此方法中指定的当前响应标头集和数字响应代码将响应发送回客户端....
请按照您的示例尝试以下操作:
@Override
public void handle(HttpExchange he) throws IOException {
GetObjectRequest getObjectRequest = GetObjectRequest.builder()
.bucket(bucketName)
.key(id + "/files/" + id + ".txt")
.build();
// Optional,and according to your file extension
he.getResponseHeaders().set("Content-type","text/plain");
// Set the `responseLength` to zero,from the docs: chunked transfer encoding
// will be used and an arbitrary amount of data may be sent.
he.sendResponseHeaders(200,0);
// The rest of your code
OutputStream os = he.getResponseBody();
s3Client.getObject(getObjectRequest,ResponseTransformer.toOutputStream(os));
os.close();
//...
}
您可以先读取 S3Client
返回的全部信息,然后将其包装在您的处理程序中:
@Override
public void handle(HttpExchange he) throws IOException {
// Fist,download actual object from S3 in the way you consider appropriate
// This fragment of code could be refactored and be defined in its own
// class/method
GetObjectRequest getObjectRequest = GetObjectRequest.builder()
.bucket(bucketName)
.key(id + "/files/" + id + ".txt")
.build();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
s3Client.getObject(getObjectRequest,ResponseTransformer.toOutputStream(bos));
byte[] bytes = bos.toByteArray();
// Perform the actual exchange
// Optional,"text/plain");
he.sendResponseHeaders(200,bytes.length);
// Please,perform the optimizations (buffering,etcetera) that you
// consider necessary when writing the information to the user
he.getResponseBody().write(bytes);
he.close();
}
如果需要,第二种方法将允许您重构代码,将与 S3 交互相关的逻辑与与 HTTP 包装代码相关的逻辑区分开来。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。