亚马逊s3上传多个android文件

时间:2017-09-05 16:23:57

标签: android amazon-web-services

我有一个ImageFiles的ArrayList,我想上传到Amazon s3。他们的文档提供了这段代码:

credentials = new BasicAWSCredentials(key, secret);
 s3 = new AmazonS3Client(credentials);               
transferUtility = new TransferUtility(s3, getContext());
observer.setTransferListener(new TransferListener() {
@Override
public void onStateChanged(int id, TransferState state) {

}

@Override
public void onProgressChanged(int id, long bytesCurrent, long bytesTotal) {
}
@Override
public void onError(int id, Exception ex) {

                                                }
                                            });
observer = transferUtility.upload(
 "buket name",
upload_file.getNew_name(),
new File(upload_file.getFile_path()));

但是这段代码只需要一个文件。如何一次上传多个文件?如果他们不允许这样,那么用户可以提出更多请求,那么可以选择做什么?

5 个答案:

答案 0 :(得分:2)

我知道我来晚了,但是它将帮助其他会来这里寻找答案的人。

当前,上传多个文件的唯一选择是使用循环,将列表中的文件作为单个文件传递,但这是我昨晚发现并实现的。到目前为止,我已经对其进行了多次测试。

此方法的优点是,它对每个文件同时运行,而不必等待每个文件先上传或下载即可对下一个文件进行操作。

这是我发现的here,但我对其进行了一些修改,以便在Kotlin中使用。

  • 首先,创建一个类,我将其命名为MultiUploaderS3-

     import android.content.Context
     import com.amazonaws.mobileconnectors.s3.transferutility.TransferListener
     import com.amazonaws.mobileconnectors.s3.transferutility.TransferState
     import com.amazonaws.mobileconnectors.s3.transferutility.TransferUtility
     import io.reactivex.Completable
     import io.reactivex.Observable
     import io.reactivex.Single
     import java.io.File
    
     class MultiUploaderS3 {
    
         private fun transferUtility(context: Context): Single<TransferUtility?>? {
             return Single.create { emitter ->
                 emitter.onSuccess(
                 TransferUtility(s3ClientInitialization(context), context)
                 )
             }
         }
    
         fun uploadMultiple(fileToKeyUploads: Map<File, String>, context: Context): Completable? {
             return transferUtility(context)!!
                 .flatMapCompletable { transferUtility ->
                     Observable.fromIterable(fileToKeyUploads.entries)
                         .flatMapCompletable { entry ->
                             uploadSingle(
                                 transferUtility,
                                 entry.key,
                                 entry.value
                             )
                         }
                 }
         }
    
             private fun uploadSingle(
             transferUtility: TransferUtility,
             aLocalFile: File?,
             toRemoteKey: String?
         ): Completable? {
             return Completable.create { emitter ->
                 transferUtility.upload(bucketName,toRemoteKey, aLocalFile)
                     .setTransferListener(object : TransferListener {
                         override fun onStateChanged(
                             id: Int,
                             state: TransferState
                         ) {
                             if (TransferState.FAILED == state) {
                                 emitter.onError(Exception("Transfer state was FAILED."))
                             } else if (TransferState.COMPLETED == state) {
                                 emitter.onComplete()
                             }
                         }
    
                         override fun onProgressChanged(
                             id: Int,
                             bytesCurrent: Long,
                             bytesTotal: Long
                         ) {
                         }
    
                         override fun onError(id: Int, exception: Exception) {
                             emitter.onError(exception)
                         }
                     })
             }
         }
    
     }
    
  • 我创建了一个用于返回S3Client的函数,如下所示-

    fun s3ClientInitialization(context: Context): AmazonS3 {
        val cognitoCachingCredentialsProvider = CognitoCachingCredentialsProvider(
            context,
            your key,
            region
        )
        return AmazonS3Client(
            cognitoCachingCredentialsProvider,
            Region.getRegion(Regions.YOUR_REGION)
        )
    }
    
  • 然后,将其命名为-

     val map: Map<File, String> = yourArrayList.map {it to Your_Key_For_Each_File}.toMap()
     MultiUploaderS3().uploadMultiple(map, this)
         .subscribeOn(Schedulers.io())
         .observeOn(Schedulers.io())
         .subscribe {
             runOnUiThread {
                 Toast(this@AddActivity, "Uploading completed", Toast.LENGTH_LONG).show()
             }
          }
    

我已经共享了完整的工作代码,您可以根据需要进行更改。您也可以在同一类中使用上述MultiUploaderS3类,这显然会使事情更容易访问TransferListener

要进行下载,请更改

transferUtility.upload(bucketName,toRemoteKey, aLocalFile)uploadSingle()

transferUtility.download(bucketName, fromRemoteKey, aLocalFile)

并命名为

val map: Map<File, String> = yourKeysArrayList.map {Your_FILE_For_Each_KEY to it}.toMap()

这将使本地文件路径映射传递给键。

我已经尝试过一次运行一次上传10个文件,并且上传所有文件大约需要4-5秒,但是这也取决于您的互联网连接。我希望下载部分也能正常工作。询问我是否有东西,或检查我的Github

答案 1 :(得分:1)

您可以为此任务创建可观察的

 public Observable<AWSFile> upload(List<String> paths) {
        List<Observable<AWSFile>> list = new ArrayList<>();
        for (String path: paths) {
            list.add(upload(path));
        }
        return Observable.concat(list);
    }

public Observable<AWSFile> upload(String filePath) {
        if (filePath == null) {
            Log.d(TAG, "uploadWithTransferUtility: ");
            return Observable.never();
        }
        return Observable.create(emitter -> {
            File file = new File(filePath);
            TransferObserver observer = awsUtil.getTransferUtility(context).upload(awsUtil.getAwsConstants().BUCKET_NAME, file);
            observer.setTransferListener(new TransferListener() {
                @Override
                public void onStateChanged(int id, TransferState state) {
                    stateChanged(id, state);
                    emitter.onNext(new AWSFile(id,state,file.getName()));
                }

                @Override
                public void onProgressChanged(int id, long bytesCurrent, long bytesTotal) {
                    progressChanged(id, bytesCurrent, bytesTotal);
                }

                @Override
                public void onError(int id, Exception ex) {
                    error(id,ex);
                    emitter.onError(ex);
                }
            });
            emitter.setCancellable(observer::cleanTransferListener);
        });
}

这只是片段,您可以将其用于许多文件或一个文件。

编辑: AWSFile.java

public class AWSFile {
    private int id;
    private TransferState newState;
    private String filename;
}

答案 2 :(得分:0)

答案 3 :(得分:0)

您可以将上传代码移至方法并将其传递给文件路径。 然后,您可以在文件路径列表上循环该方法。至少我是这样做的。如果您需要任何进一步的帮助,请告诉我。

答案 4 :(得分:0)

@Lalit-Fauzdar 回答和提到的参考是解决问题的方法。我正在分享对实施的轻微升级

class MultiUploaderS3Client(bucketName:String) {

    var bucketName = bucketName

    fun uploadMultiple(fileToKeyUploads: MutableMap<String,File>, transferUtility: TransferUtility): Completable? {
        return transferUtility(transferUtility)
            .flatMapCompletable { transferUtility ->
                Observable.fromIterable(fileToKeyUploads.entries)
                    .flatMapCompletable { entry ->
                        uploadSingle(
                            transferUtility,
                            entry.value,
                            entry.key
                        )
                    }
            }
    }

    private fun transferUtility(transferUtility: TransferUtility): Single<TransferUtility?> {
        return Single.create { emitter ->
            emitter.onSuccess(
                transferUtility
            )
        }
    }

    private fun uploadSingle(
        transferUtility: TransferUtility?,
        aLocalFile: File?,
        toRemoteKey: String?
    ): Completable? {
        return Completable.create { emitter ->
            transferUtility?.upload(bucketName,toRemoteKey, aLocalFile)
                ?.setTransferListener(object : TransferListener {
                    override fun onStateChanged(
                        id: Int,
                        state: TransferState
                    ) {
                        if (TransferState.FAILED == state) {
                            emitter.onError(Exception("Transfer state was FAILED."))
                        } else if (TransferState.COMPLETED == state) {
                            emitter.onComplete()
                        }
                    }

                    override fun onProgressChanged(
                        id: Int,
                        bytesCurrent: Long,
                        bytesTotal: Long
                    ) {
                    }

                    override fun onError(id: Int, exception: Exception) {
                        emitter.onError(exception)
                    }
                })
        }
    }

}
<块引用>

val multiUploadHashMap = mutableMapOf<String,File>()

MultiUploaderS3Client(AWSConfig.misTicketFilesBucketName).uploadMultiple(multiUploadHashMap, transferUtility)
                        ?.subscribeOn(Schedulers.io())
                        ?.observeOn(Schedulers.io())
                        ?.subscribe {
                            //Called when all files uploaded
                            Runnable { callback.onComplete(_Result.Success<String>("uploaded successfully")) }
                            handler.post(returnCallback)
                        }