我有一个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()));
但是这段代码只需要一个文件。如何一次上传多个文件?如果他们不允许这样,那么用户可以提出更多请求,那么可以选择做什么?
答案 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)
TransferUtility Class,
http://docs.aws.amazon.com/mobile/sdkforandroid/developerguide/s3transferutility.html
保留以下历史答案,不推荐使用以下类。
您需要查看TransferManager类,
它有多文件上传选项。
答案 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)
}