我正在尝试使用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 closed”或者没有报告错误,但只读取了部分对象。
请注意,BufferedInputStream
不需要IOUtils.toByteArray(...)
,如果它存在与否则无效。
在调试器中逐行单步执行代码时,似乎不会出现此问题。
这发生在我的Android 2.3.3设备和3.2设备上。它发生在WiFi和3G上。
有什么想法吗?
PS>对象大约250k
答案 0 :(得分:4)
问题是客户端正在收集垃圾。要修复它,您需要保持对S3Client的显式引用。
错误的流程如下:
IMO,亚马逊这是一个非常糟糕的错误。为什么S3对象输入流没有引用回客户端对我来说是一个谜。
以下是AWS论坛上的主题:https://forums.aws.amazon.com/thread.jspa?threadID=83326
答案 1 :(得分:2)
你可能已经解决了这个问题,但我找不到正确的答案,最后我自己搞清楚了,所以这就解决了:
getObjectContent方法文档非常清楚关闭InputStream:
S3ObjectInputStream com.amazonaws.services.s3.model.S3Object.getObjectContent()
获取包含此对象内容的输入流。调用者应尽快关闭此输入流,因为对象内容不会缓存在内存中,而是直接从Amazon S3流式传输。
你犯的是和我使用InputStream(S3Object)一样的错误,好像闭包是透明的。
我猜你需要从S3获取一个图像才能在Android上使用,所以这里有一个返回Bitmap的示例方法。它确实适用于任何类型的输入。
private Bitmap getFromStore(String fileName) {
AmazonS3Client client = new AmazonS3Client(new BasicAWSCredentials(ACCESS_KEY, SECRET_KEY));
S3Object o = client.getObject(BUCKET, fileName);
InputStream is = o.getObjectContent();
Bitmap image = null;
try {
// Use the inputStream and close it after.
image = BitmapFactory.decodeStream(is);
} finally {
try {
is.close();
} catch (IOException e) {
Log.w(TAG, "Error trying to close image stream. ", e);
}
}
return image;
}
以防万一,不要忘记在不同的线程上执行此操作,然后再执行UI。
祝你好运,答案 2 :(得分:1)
How to write an S3 object to a file?
我会尝试循环内容,就像上面问题中的答案一样。缓冲很好,但是......
你也可以尝试不使用IOUtil,毕竟java中还有其他选项。
答案 3 :(得分:0)
无需继续重新初始化s3。
在onCreate
中,拨打电话以初始化s3Object
和s3Client
。
然后使用asynctask
中的来电。这样,您的s3Client
将保留相同的数据,并且在执行while读取时永远不会关闭与s3的套接字连接。
S3Client s3Client;
S3Object s3Object;
onCreate() {
s3Client = new AmazonS3Client(new BasicSessionCredentials(
Constants.ACCESS_KEY_ID, Constants.SECRET_KEY, Constants.TOKEN
));
object = new S3Object();
}
doinbackground() {
object = s3Client.getObject(new GetObjectRequest(Constants.getBucket(), id +".png"));
}
/****** add this in your onCreate ******/
AmazonS3Client client = getConnection(userCredentials);