Android AWS s3 SDK 下载抛出“套接字已关闭”错误例外或提前终止
我正在尝试使用 AWS Android SDK 1.0.4 或 1.0.3 从 S3 下载对象。
这是我的代码:
AmazonS3Client client = getConnection(userCredentials);
S3Object obj = client.getObject(workspaceName, objectName);
ObjectMetadata meta = obj.getObjectMetadata();
long size = meta.getContentLength();
logger.info("S3 object length: "+size);
InputStream is = new BufferedInputStream(obj.getObjectContent());
byte[] fragmentBytes = IOUtils.toByteArray(is);
logger.info("Read bytes: "+ fragmentBytes.length);
有时(很少)有效。大多数情况下,要么抛出“java.net.SocketException:Socket is close”,要么不报告错误,但只读取对象的一部分。
请注意,BufferedInputStream
对于 IOUtils.toByteArray(...)
来说不是必需的,并且它存在或不存在也没有什么区别。
在调试器中逐行单步执行代码时似乎不会出现该问题。
我的 Android 2.3.3 设备和 3.2 设备上会发生这种情况。它通过 WiFi 和 3G 进行。
有什么想法吗?
附注>这些物体大约有 250k 大
I'm trying to download an object from S3 using the AWS Android SDK 1.0.4 or 1.0.3.
This is my code:
AmazonS3Client client = getConnection(userCredentials);
S3Object obj = client.getObject(workspaceName, objectName);
ObjectMetadata meta = obj.getObjectMetadata();
long size = meta.getContentLength();
logger.info("S3 object length: "+size);
InputStream is = new BufferedInputStream(obj.getObjectContent());
byte[] fragmentBytes = IOUtils.toByteArray(is);
logger.info("Read bytes: "+ fragmentBytes.length);
This sometimes, rarely, works. Most of the time either an "java.net.SocketException: Socket is closed" is thrown or no error is reported but only part of the object is read.
Note, that the BufferedInputStream
should not be necessary for IOUtils.toByteArray(...)
and it makes no difference if it is there or not.
The problem does not seem to occur when stepping through the code line by line in a debugger.
This happens on my Android 2.3.3 device and 3.2 device. It happens over WiFi and 3G.
Any ideas?
ps> The objects are about 250k big
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
问题是客户端正在被垃圾收集。要修复此问题,您需要保留对 S3Client 的显式引用。
该错误的流程如下:
IMO,这是亚马逊的一个非常严重的错误。为什么 S3 对象输入流没有返回客户端的引用对我来说是一个谜。
以下是 AWS 论坛上的主题:https://forums.aws.amazon.com /thread.jspa?threadID=83326
The issue is that the client is being Garbage Collected. To fix it, you need to keep an explicit reference to the S3Client.
The flow of the bug is as follows:
IMO, this is a very bad bug by Amazon. Why the S3 object input stream does not have a reference back to the client is a mystery to me.
Here's the thread on the AWS forums: https://forums.aws.amazon.com/thread.jspa?threadID=83326
您可能已经解决了这个问题,但我找不到正确的答案,最终自己解决了这个问题,所以解决方案如下:
getObjectContent 方法文档非常清楚有关关闭 InputStream 的信息:
您犯了与我使用 InputStream (S3Object) 相同的错误,就好像闭包是透明的一样。
我猜您需要从 S3 获取图像才能在 Android 上使用,因此这里有一个返回位图的示例方法。它确实适用于任何类型的输入。
以防万一,不要忘记在与 UI 不同的线程上执行此操作。
祝你好运,
You probably already solved this but I could not find the correct answer and ended up figuring it out by myself, so here goes the solution:
The getObjectContent methods documentation is very clear about closing the InputStream:
You are making the same mistake as I was of using the InputStream (S3Object) as if closure was transparent.
I am guessing you need to get an image from S3 to be used on Android, so here goes an example method that returns a Bitmap. It really applies to any kind of input.
Just in case, dont forget to execute this on a different thread then the UI.
Good luck,
嗯,看来你并不孤单。帖子中接受的答案谈到了您的问题。
如何将 S3 对象写入文件?
我会尝试循环内容,就像上面问题的答案一样。 Buffered 很好,但是……
你也可以尝试不使用 IOUtil,毕竟 java 中还有其他选项。
Well, it seems you are not alone. The accepted in the post answer talks of your problem.
How to write an S3 object to a file?
I would try looping the content like the answer in the question above. Buffered is good, but....
You could also try not using the IOUtil, after all there are other options in java.
无需不断重新初始化 s3。
在
onCreate
中,调用初始化s3Object
和s3Client
。然后在您的
asynctask
中使用该调用。这样,您的 s3Client 将保留相同的数据,并且在执行 while 读取时永远不会关闭与 s3 的套接字连接。no need to keep re-initializing s3.
In your
onCreate
, make the call to initializes3Object
ands3Client
.Then use the call in your
asynctask
. This way, yours3Client
will keep the same data and never close the socket connection with s3 when doing the while read.