【问题标题】:Upload Media From Android Gallery to AWS S3将媒体从 Android 库上传到 AWS S3
【发布时间】:2021-04-26 18:53:38
【问题描述】:

我在我的 Android 应用项目上使用 Amplify Storage 工作了很长时间,但我遇到了一个我没有找到解决方案的问题。

我想从图库中检索图像/视频并将其上传到 S3,但我总是收到“光标”错误,它总是返回 null。

有没有更好的方法将 Uri 数据转换为文件,以便我可以将其上传到 S3?

这是我的代码:

public void openPhotoGallery(View v) {

    Intent intent = new Intent();
    intent.setType("image/*");
    intent.setAction(Intent.ACTION_GET_CONTENT);
    startActivityForResult(Intent.createChooser(intent, "Select file to upload "), 8);

}

@Override
protected void onActivityResult(int requestCode, final int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (resultCode == RESULT_OK && requestCode == 8) {

        Uri selectedMediaUri = data.getData();
        String filePath = getPath(selectedMediaUri);

        File file = saveVideoToInternalStorage(filePath);

        Amplify.Storage.uploadFile("test/image", file, result -> {
            Log.i("MyAmplifyApp", "Successfully uploaded: " + result.getKey());
            file.delete();
            }, error -> {
            Log.e("MyAmplifyApp", "Upload failed", error);
        });
    }
 }

 public String getPath(Uri uri) {

    String[] projection = { MediaStore.Images.Media.DATA };
    Cursor cursor = managedQuery(uri, projection, null, null, null);
    int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); // Line of error
    cursor.moveToFirst();

    return cursor.getString(column_index);
}

private File saveVideoToInternalStorage (String filePath) {

    File newfile = null;
    try {

        File currentFile = new File(filePath);
        ContextWrapper cw = new ContextWrapper(getApplicationContext());


        newfile = new File(this.getFilesDir().getPath().toString() + "/video1.mp4");

        if(currentFile.exists()){

            InputStream in = new FileInputStream(currentFile);
            OutputStream out = new FileOutputStream(newfile);

            // Copy the bits from instream to outstream
            byte[] buf = new byte[1024];
            int len;

            while ((len = in.read(buf)) > 0) {
                out.write(buf, 0, len);
            }

            in.close();
            out.close();

            Log.v("", "Video file saved successfully.");
        } else {
            Log.v("", "Video saving failed. Source file missing.");
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return newfile;
}

我总是有这个错误:

E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.abdulelah.taajerpartners, PID: 24163
java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=8, result=-1, data=Intent { dat=content://media/external/images/media/419319 flg=0x1 (has extras) }} to activity {com.abdulelah.taajerpartners/com.ajjerly.partners.TestActivity}: java.lang.NullPointerException: Attempt to invoke interface method 'int android.database.Cursor.getColumnIndexOrThrow(java.lang.String)' on a null object reference
    at android.app.ActivityThread.deliverResults(ActivityThread.java:5078)
    at android.app.ActivityThread.handleSendResult(ActivityThread.java:5120)
    at android.app.servertransaction.ActivityResultItem.execute(ActivityResultItem.java:49)
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2199)
    at android.os.Handler.dispatchMessage(Handler.java:112)
    at android.os.Looper.loop(Looper.java:216)
    at android.app.ActivityThread.main(ActivityThread.java:7625)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:524)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:987)
 Caused by: java.lang.NullPointerException: Attempt to invoke interface method 'int android.database.Cursor.getColumnIndexOrThrow(java.lang.String)' on a null object reference
    at com.ajjerly.partners.TestActivity.getPath(TestActivity.java:114)
    at com.ajjerly.partners.TestActivity.onActivityResult(TestActivity.java:72)
    at android.app.Activity.dispatchActivityResult(Activity.java:7797)
    at android.app.ActivityThread.deliverResults(ActivityThread.java:5071)

【问题讨论】:

  • 尝试将漂亮的 uri 转换为 File 实例是一个非常糟糕的主意。看看 Alpine 是否可以从流中上传。
  • 此外,我不明白如果您可以将 uri 转换为文件实例,那么您首先要复制该文件。请解释一下。

标签: java android amazon-s3 aws-amplify amplify


【解决方案1】:

从 Android 10 开始,如果文件存储在您的应用程序目录中,您只能获取给定 Uri 的路径。画廊中的照片不符合此标准。请参阅Storage updates in Android 了解更多详情。

一种解决方案是直接从您的Uri 创建一个InputStream,如下所示:

InputStream inStream = getContentResolver().openInputStream(uri);

然后,您可以将其保存到File,就像您在saveVideoToInternalStorage 中所做的那样,然后将File 传递给Amplify.Storage.uploadFile

更好/更简单的解决方案是使用Amplify.Storage.uploadInputStream API(而不是Amplify.Storage.uploadFile),如下所示:

InputStream inStream = getContentResolver().openInputStream(uri);
Amplify.Storage.uploadInputStream("test/image", inputStream, 
    result -> {
        Log.i("MyAmplifyApp", "Successfully uploaded: " + result.getKey());
    }, error -> {
        Log.e("MyAmplifyApp", "Upload failed", error);
    }
);

在底层,Amplify 库实际上与您正在做的事情相同 - 它将 InputStream 作为 File 写入临时目录,上传 File,然后将其从临时目录中删除完成。

【讨论】:

    猜你喜欢
    • 2012-10-24
    • 2018-03-16
    • 2019-02-01
    • 2016-02-21
    • 1970-01-01
    • 1970-01-01
    • 2019-05-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多