Я долго пытался это решить, но безуспешно. Я использую AWS Android SDK для загрузки файлов в AWS S3, а иногда файлы загружаются на сервер, а другие - нет. Выполняется команда putObject, но она просто «зависает» и блокирует выполнение кода на этой строке.AmazonS3Client.putObject не работает, если я сначала вызываю AmazonS3Client.listObjects
Попробовав комментировать фрагменты кода, чтобы найти источник проблемы, я пришел к выводу, что это происходит, потому что я вызываю listObject перед загрузкой.
Я не могу удалить этот список объектов, потому что мне нужно получить имена файлов при запуске приложения, и любые загрузки будут выполняться только после того, как пользователь выберет то, что он хочет загрузить.
Обычно я загружаю фотографии из своей ячейки, размером от 1 до 1,3 МБ, и это завершает загрузку менее чем за 30 секунд. Если я вызываю listObjects, он «зависает». Почему это происходит? Кто-нибудь знает, что происходит? Здесь идет несколько строк моего кода:
Во андроид OnCreate:
weather_data = new ArrayList<Weather>();
ObjectListing objectListing = s3Client.listObjects(new ListObjectsRequest().withBucketName(lista_de_baldes.get(0).getName()).withPrefix("Thumbs"));
for (S3ObjectSummary objectSummary : objectListing.getObjectSummaries())
weather_data.add(new Weather(R.drawable.jogo, objectSummary.getKey().replace("Thumbs/", "")));
После того, как пользователь выбрал фотографию для загрузки (выполняются во время doInBackground из класса, который расширяет AsyncTask для предотвращения основного потока от замерзания) :
File arquivo = new java.io.File(filePath);
PutObjectRequest por = new PutObjectRequest(
lista_de_baldes.get(0).getName(),
filePath.substring(filePath.lastIndexOf('/') + 1),
arquivo
);
s3Client.putObject(por);
Это ulso, используя тот же ковш, тот же регион и в той же зоне. ОбъектList также отлично работает.
Редактировать: Я решил проблему, установив переменную AmazonS3Client снова в код загрузки. Например:
s3Client = new AmazonS3Client(
new BasicAWSCredentials(Constants.ACCESS_KEY_ID, Constants.SECRET_KEY)
);
s3Client.setRegion(Region.getRegion(Regions.SA_EAST_1));
Но это не имеет смысла для меня, потому что это глобальная переменная. Похоже, что он просто «заблокирован» после того, как я загрузил список объектов. Кто-нибудь знает, что происходит?
Редактировать: В соответствии с требованиями здесь больше кода.
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
s3Client = new AmazonS3Client(
new BasicAWSCredentials(Constants.ACCESS_KEY_ID, Constants.SECRET_KEY)
);
//mudei de US_WEST_2 para SA_EAST_1 (south america) para acessar um bucket criado em SP/Brazil
s3Client.setRegion(Region.getRegion(Regions.SA_EAST_1));
lista_de_baldes = s3Client.listBuckets();
setContentView(R.layout.main);
weather_data = new ArrayList<Weather>();
ObjectListing objectListing = s3Client.listObjects(new ListObjectsRequest().withBucketName(lista_de_baldes.get(0).getName()).withPrefix("Thumbs"));
for (S3ObjectSummary objectSummary : objectListing.getObjectSummaries()) {
File arquivo_thumb = new File(getCacheDir() + File.separator + objectSummary.getKey().replace("Thumbs/", ""));
weather_data.add(new Weather(R.drawable.jogo, arquivo_thumb.getName().replace(".png", ".jpg")));
if(arquivo_thumb.exists())
continue;
InputStream input = null;
try {
ResponseHeaderOverrides override = new ResponseHeaderOverrides();
override.setContentType("image/jpeg");
GeneratePresignedUrlRequest urlRequest = new GeneratePresignedUrlRequest(
lista_de_baldes.get(0).getName(),
"Thumbs/" + arquivo_thumb.getName()
);
urlRequest.setResponseHeaders(override);
URL url = s3Client.generatePresignedUrl(urlRequest);
...
}
Часть загрузки:
protected S3TaskResult doInBackground(Uri... uris) {
if (uris == null || uris.length != 1) {
return null;
}
// The file location of the image selected.
Uri selectedImage = uris[0];
String[] filePathColumn = { MediaStore.Images.Media.DATA };
Cursor cursor = getContentResolver().query(selectedImage,
filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
filePath = cursor.getString(columnIndex);
cursor.close();
S3TaskResult result = new S3TaskResult();
// Put the image data into S3.
try {
// Content type is determined by file extension.
File arquivo = new java.io.File(filePath);
PutObjectRequest por = new PutObjectRequest(
lista_de_baldes.get(0).getName(),
filePath.substring(filePath.lastIndexOf('/') + 1),
arquivo
);
por.setCannedAcl(CannedAccessControlList.PublicRead);
s3Client.putObject(por);
Нет, listObjects не завернут в AsyncTask. Он просто работает по методу onCreate. Ничего не выполняется до тех пор, пока listObjects не завершится. –
AmazonS3Client не должен блокировать putObject, если вы сначала вызываете listObjects. Я не знаю о блокировке на стороне обслуживания S3. Несколько вещей: 1) как вы сказали, AmazonS3Client предназначен для повторного использования. 2) listObjects - это сетевой запрос. Он заблокирует поток пользовательского интерфейса. 3) полный код и трассировка стека (если таковые имеются) могут помочь нам идентифицировать проблему для вас. – Yangfan
Отредактировал вопрос и добавил код. listObjects не используется внутри AsyncTask, по крайней мере пока. –