2013-04-18 1 views
1

Я долго пытался это решить, но безуспешно. Я использую 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); 

ответ

0

обернута listObjects в AsyncTask? Подождите, пока не закончится listObjects? FYI, так как уровень Honeycomb уровня 11, по умолчанию несколько экземпляров AsyncTask выполняются последовательно.

+0

Нет, listObjects не завернут в AsyncTask. Он просто работает по методу onCreate. Ничего не выполняется до тех пор, пока listObjects не завершится. –

+0

AmazonS3Client не должен блокировать putObject, если вы сначала вызываете listObjects. Я не знаю о блокировке на стороне обслуживания S3. Несколько вещей: 1) как вы сказали, AmazonS3Client предназначен для повторного использования. 2) listObjects - это сетевой запрос. Он заблокирует поток пользовательского интерфейса. 3) полный код и трассировка стека (если таковые имеются) могут помочь нам идентифицировать проблему для вас. – Yangfan

+0

Отредактировал вопрос и добавил код. listObjects не используется внутри AsyncTask, по крайней мере пока. –