将图像从 Android 上传到 Amazon S3?

Posted

技术标签:

【中文标题】将图像从 Android 上传到 Amazon S3?【英文标题】:Upload an image from Android to Amazon S3? 【发布时间】:2011-11-10 17:26:19 【问题描述】:

我需要将位图上传到 Amazon S3。我从未使用过 S3,并且文档证明没有什么帮助,因为我看不到任何内容可以满足这一特定要求。不幸的是,我很难在这个项目上找到时间花一整天的时间来学习它是如何组合在一起的,所以希望你们中的一个好心人能给我一些建议。

您能否指出一个参考源,该参考源解释了如何将文件推送到 S3,并获得一个 URL 参考作为回报?

更具体地说: - 使用 S3 android SDK 时凭证在哪里? - 我需要在上传文件之前创建一个存储桶,还是它们可以存在于存储桶之外? - 我使用哪种 SDK 方法将位图推送到 S3? - 我是否认为我需要 CORE 和 S3 库来做我需要的事情,而不需要其他库?

【问题讨论】:

【参考方案1】:
String      ACCESS_KEY="****************",
            SECRET_KEY="****************",
            MY_BUCKET="bucket_name",
            OBJECT_KEY="unique_id";              
  AWSCredentials credentials = new BasicAWSCredentials(ACCESS_KEY, SECRET_KEY);
                AmazonS3 s3 = new AmazonS3Client(credentials);
                java.security.Security.setProperty("networkaddress.cache.ttl" , "60");
                s3.setRegion(Region.getRegion(Regions.AP_SOUTHEAST_1));
                s3.setEndpoint("https://s3-ap-southeast-1.amazonaws.com/");
                List<Bucket> buckets=s3.listBuckets();
                for(Bucket bucket:buckets)
                    Log.e("Bucket ","Name "+bucket.getName()+" Owner "+bucket.getOwner()+ " Date " + bucket.getCreationDate());
                
                Log.e("Size ", "" + s3.listBuckets().size());
                TransferUtility transferUtility = new TransferUtility(s3, getApplicationContext());
                UPLOADING_IMAGE=new File(Environment.getExternalStorageDirectory().getPath()+"/Screenshot.png");
                TransferObserver observer = transferUtility.upload(MY_BUCKET,OBJECT_KEY,UPLOADING_IMAGE);
                observer.setTransferListener(new TransferListener() 
                    @Override
                    public void onStateChanged(int id, TransferState state) 
                        // do something
                        progress.hide();
                        path.setText("ID "+id+"\nState "+state.name()+"\nImage ID "+OBJECT_KEY);

                    

                    @Override
                    public void onProgressChanged(int id, long bytesCurrent, long bytesTotal) 
                        int percentage = (int) (bytesCurrent / bytesTotal * 100);
                        progress.setProgress(percentage);
                        //Display percentage transfered to user
                    

                    @Override
                    public void onError(int id, Exception ex) 
                        // do something
                        Log.e("Error  ",""+ex );
                    

                );

【讨论】:

感谢这个很好的例子,我在文档中找不到类似的例子。事实上,我只需要前几行,如何设置凭据和区域。 @Andan:上面的工作正常。你知道使用TransferUtility.download()方法下载图像后如何返回位图吗?以下不起作用。 protected Bitmap processBitmap(String d) File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/" + d); transferObserver = transferUtility.download(Constants.BUCKET_NAME, d, file ); BitmapFactory.Options options = new BitmapFactory.Options(); options.inPreferredConfig = Bitmap.Config.ARGB_8888; Bitmap bm = BitmapFactory.decodeFile(transferObserver.getAbsoluteFilePath(), options); return bm; 【参考方案2】:

查看Amazon S3 API documentation,了解使用 Amazon S3 可以做什么和不可以做什么。请注意,有两个 API,一个更简单的 REST API 和一个涉及更多的 SOAP API。

您可以编写自己的代码来发出 HTTP 请求以与 REST API 交互,或者使用 SOAP 库来使用 SOAP API。所有亚马逊服务都有这些标准 API 端点(REST、SOAP),理论上你可以用任何编程语言编写客户端!

对于 Android 开发人员来说,幸运的是,亚马逊已经发布了 a (Beta) SDK,它可以为您完成所有这些工作。还有Getting Started 指南和Javadocs。使用此 SDK,您应该能够在几个小时内将 S3 与您的应用程序集成。

入门指南附带完整示例,并展示了如何提供所需的凭据。

从概念上讲,Amazon S3 将数据存储在 Buckets 中,其中 Bucket 包含 Objects。通常每个应用程序使用一个存储桶,并添加任意数量的对象。 S3 不支持或有任何文件夹概念,但您可以在对象名称中添加斜杠 (/)。

【讨论】:

谢谢大卫。我花了一些时间阅读入门指南以及文档和示例,但到目前为止,要找到合适的示例代码是一个缓慢的过程。亚马逊似乎已经为那些将要学习所有内容并花费大量时间的人编写了文档——我没有那种奢侈,我只想塞入一个文件,然后做其他事情。看来我需要花更多的时间,这是一种耻辱。 我知道你的意思。我现在花了三天时间试图找到一个易于理解的示例,用于将图像安全地上传到 s3。 老实说,我认为他们应该改进文档!【参考方案3】:

我们可以直接使用“Amazone s3”存储桶在服务器上存储任何类型的文件,并且我们不需要将任何文件发送到 Api 服务器,这将减少请求时间。

Gradle 文件:-

 compile 'com.amazonaws:aws-android-sdk-core:2.2.+'
    compile 'com.amazonaws:aws-android-sdk-s3:2.2.+'
    compile 'com.amazonaws:aws-android-sdk-ddb:2.2.+'

清单文件:-

<service android:name="com.amazonaws.mobileconnectors.s3.transferutility.TransferService"
            android:enabled="true" />

任何类中的 FileUploader 函数:-

 private void setUPAmazon() 
 //we Need Identity Pool ID  like :- "us-east-1:f224****************8"
        CognitoCachingCredentialsProvider credentialsProvider = new CognitoCachingCredentialsProvider(getActivity(),
                "us-east-1:f224****************8", Regions.US_EAST_1);
        AmazonS3 s3 = new AmazonS3Client(credentialsProvider);
        final TransferUtility transferUtility = new TransferUtility(s3, getActivity());
        final File file = new File(mCameraUri.getPath());
        final TransferObserver observer = transferUtility.upload(GeneralValues.AMAZON_BUCKET, file.getName(), file, CannedAccessControlList.PublicRead);
        observer.setTransferListener(new TransferListener() 
            @Override
            public void onStateChanged(int id, TransferState state) 
                Log.e("onStateChanged", id + state.name());
                if (state == TransferState.COMPLETED) 
                    String url = "https://"+GeneralValues.AMAZON_BUCKET+".s3.amazonaws.com/" + observer.getKey();
                    Log.e("URL :,", url);
//we just need to share this File url with Api service request.  
                
            

            @Override
            public void onProgressChanged(int id, long bytesCurrent, long bytesTotal) 
            

            @Override
            public void onError(int id, Exception ex) 
                Toast.makeText(getActivity(), "Unable to Upload", Toast.LENGTH_SHORT).show();
                ex.printStackTrace();
            
        );
    

【讨论】:

【参考方案4】:

您可以使用下面提到的类将数据上传到 amazon s3 存储桶。

public class UploadAmazonS3

private CognitoCachingCredentialsProvider credentialsProvider = null;
private AmazonS3Client s3Client = null;
private TransferUtility transferUtility = null;
private static UploadAmazonS3 uploadAmazonS3;

/**
 * Creating single tone object by defining private.
 * <P>
 *     At the time of creating
 * </P>*/
private UploadAmazonS3(Context context, String canito_pool_id)

    /**
     * Creating the object of the getCredentialProvider object. */
    credentialsProvider=getCredentialProvider(context,canito_pool_id);
    /**
     * Creating the object  of the s3Client */
    s3Client=getS3Client(context,credentialsProvider);

    /**
     * Creating the object of the TransferUtility of the Amazone.*/
    transferUtility=getTransferUtility(context,s3Client);



public static UploadAmazonS3 getInstance(Context context, String canito_pool_id)

    if(uploadAmazonS3 ==null)
    
        uploadAmazonS3 =new UploadAmazonS3(context,canito_pool_id);
        return uploadAmazonS3;
    else
    
        return uploadAmazonS3;
    



/**
 * <h3>Upload_data</h3>
 * <P>
 *     Method is use to upload data in the amazone server.
 *
 * </P>*/

public void uploadData(final String bukkate_name, final File file, final Upload_CallBack callBack)

    Utility.printLog("in amazon upload class uploadData "+file.getName());

    if(transferUtility!=null&&file!=null)
    
        TransferObserver observer=transferUtility.upload(bukkate_name,file.getName(),file);
        observer.setTransferListener(new TransferListener()
        
            @Override
            public void onStateChanged(int id, TransferState state)
            
                if(state.equals(TransferState.COMPLETED))
                
                    callBack.sucess(com.tarha_taxi.R.string.AMAZON_END_POINT_LINK+bukkate_name+"/"+file.getName());
                
            

            @Override
            public void onProgressChanged(int id, long bytesCurrent, long bytesTotal)
            

            
            @Override
            public void onError(int id, Exception ex)
            
                callBack.error(id+":"+ex.toString());

            
        );
    else
    
        callBack.error("Amamzones3 is not intialize or File is empty !");
    


/**
 * This method is used to get the CredentialProvider and we provide only context as a parameter.
 * @param context Here, we are getting the context from calling Activity.*/
private CognitoCachingCredentialsProvider getCredentialProvider(Context context,String pool_id)

    if (credentialsProvider == null)
    
        credentialsProvider = new CognitoCachingCredentialsProvider(
                context.getApplicationContext(),
                pool_id, // Identity Pool ID
                AMAZON_REGION // Region
        );
    
    return credentialsProvider;


/**
 * This method is used to get the AmazonS3 Client
 * and we provide only context as a parameter.
 * and from here we are calling getCredentialProvider() function.
 * @param context Here, we are getting the context from calling Activity.*/
private AmazonS3Client getS3Client(Context context,CognitoCachingCredentialsProvider cognitoCachingCredentialsProvider)

    if (s3Client == null)
    
        s3Client = new AmazonS3Client(cognitoCachingCredentialsProvider);
        s3Client.setRegion(Region.getRegion(AMAZON_REGION));
        s3Client.setEndpoint(context.getString(com.tarha_taxi.R.string.AMAZON_END_POINT_LINK));
    
    return s3Client;


/**
 * This method is used to get the Transfer Utility
 * and we provide only context as a parameter.
 * and from here we are, calling getS3Client() function.
 * @param context Here, we are getting the context from calling Activity.*/
private TransferUtility getTransferUtility(Context context,AmazonS3Client amazonS3Client)

    if (transferUtility == null)
    
        transferUtility = new TransferUtility(amazonS3Client,context.getApplicationContext());
    
    return transferUtility;


/**
 * Interface for the sucess callback fro the Amazon uploading .
 * */
public interface Upload_CallBack

    /**
     *Method for sucess .
     * @param sucess it is true on sucess and false for falure.*/
    void sucess(String sucess);
    /**
     * Method for falure.
     * @param errormsg contains the error message.*/
    void error(String errormsg);


使用下面的方法访问上面的类:

 private void uploadToAmazon() 
    dialogL.show();
    UploadAmazonS3 amazonS3 = UploadAmazonS3.getInstance(getActivity(), getString(R.string.AMAZON_POOL_ID));
    amazonS3.uploadData(getString(R.string.BUCKET_NAME), Utility.renameFile(VariableConstants.TEMP_PHOTO_FILE_NAME, phone.getText().toString().substring(1) + ".jpg"), new UploadAmazonS3.Upload_CallBack() 
        @Override
        public void sucess(String sucess) 
            if (Utility.isNetworkAvailable(getActivity())) 
                dialogL.dismiss();
                /**
                 * to set the image into image view and
                 * add the write the image in the file
                 */
                activity.user_image.setTag(setTarget(progress_bar));
                Picasso.with(getActivity()).load(getString(R.string.AMAZON_IMAGE_LINK) + phone.getText().toString().substring(1) + ".jpg").
                        networkPolicy(NetworkPolicy.NO_CACHE).memoryPolicy(MemoryPolicy.NO_CACHE).into((Target) activity.user_image.getTag());

                Utility.printLog("amazon upload success ");
                new BackgroundForUpdateProfile().execute();
             else 
                dialogL.dismiss();
                Utility.showToast(getActivity(), getResources().getString(R.string.network_connection_fail));
            
        

        @Override
        public void error(String errormsg) 
            dialogL.dismiss();
            Utility.showToast(getActivity(), getResources().getString(R.string.network_connection_fail));
        
    );

【讨论】:

【参考方案5】:

您可以使用一个名为 S3UploadService 的库。首先,您需要将位图转换为文件。为此,请查看此帖子:

Convert Bitmap to File

S3UploadService 是一个处理上传到 Amazon S3 的库。它提供了一个名为 S3UploadService 的服务和一个静态方法,您可以在其中提供一个上下文(因此静态方法可以启动服务)、一个文件、一个布尔值,指示是否应该在上传完成后删除所述文件,并且您可以选择设置回调(不是就像一个普通的回调一样。它的工作方式在 README 文件中有解释)。

这是一个 IntentService,因此即使用户在上传时终止应用,上传也会运行(因为它的生命周期未附加到应用的生命周期)。

要使用这个库,您只需在清单中声明服务:

<application
    ...>

    ...

    <service
        android:name="com.onecode.s3.service.S3UploadService"
        android:exported="false" />
</application>

然后构建一个 S3BucketData 实例并调用 S3UploadService.upload():

    S3Credentials s3Credentials = new S3Credentials(accessKey, secretKey, sessionToken);
    S3BucketData s3BucketData = new S3BucketData.Builder()
            .setCredentials(s3Credentials)
            .setBucket(bucket)
            .setKey(key)
            .setRegion(region)
            .build();

    S3UploadService.upload(getActivity(), s3BucketData, file, null);

要添加这个库,您需要将 JitPack 存储库添加到您的根 build.gradle:

allprojects 
    repositories 
        ...
        maven  url "https://jitpack.io" 
    

然后添加依赖:

dependencies 
    compile 'com.github.OneCodeLabs:S3UploadService:1.0.0@aar'

这里是回购的链接: https://github.com/OneCodeLabs/S3UploadService

这个答案有点晚了,但我希望它对某人有所帮助

【讨论】:

【参考方案6】:

您可以在 s3 amazon 中上传图片和下载图片。你做一个简单的类使用这个 WebserviceAmazon

public class WebserviceAmazon extends AsyncTask<Void, Void, Void> 
private String mParams;
private String mResult = "x";
WebServiceInterface<String, String> mInterface;
private int mRequestType;
private  String UserId;
private Context mContext;


public WebserviceAmazon(Context context,String imagePath,String AppId,int type) 
    this.mContext = context;
    this.mParams = imagePath;
    this.mRequestType = type;
    this.UserId = AppId;


public void result(WebServiceInterface<String, String> myInterface) 
    this.mInterface = myInterface;


@Override
protected Void doInBackground(Void... params) 
    String ACCESS_KEY ="abc..";
    String SECRET_KEY = "klm...";

    try 
        if (mRequestType == 1)  // POST
            AmazonS3Client s3Client = new AmazonS3Client(new BasicAWSCredentials(ACCESS_KEY, SECRET_KEY));
            PutObjectRequest request = new PutObjectRequest("bucketName", "imageName", new File(mParams));
            s3Client.putObject(request);

            mResult = "success";
         if (mRequestType == 2)  // For get image data
            AmazonS3Client s3Client = new AmazonS3Client(new BasicAWSCredentials(ACCESS_KEY, SECRET_KEY));
            S3Object object = s3Client.getObject(new GetObjectRequest("bucketName", mParams));
            S3ObjectInputStream objectContent = object.getObjectContent();
            byte[] byteArray = IOUtils.toByteArray(objectContent);

           Bitmap bitmap = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length);



            mResult = "success";
        

     catch (Exception e) 
        mResult = e.toString();
        e.printStackTrace();
    
    return null;


@Override
protected void onPreExecute() 
    // TODO Auto-generated method stub
    super.onPreExecute();


@Override
protected void onPostExecute(Void result) 
    // TODO Auto-generated method stub
  super.onPostExecute(result);
    mInterface.success(this.mResult);



public interface WebServiceInterface<E, R> 
    public void success(E reslut);

    public void error(R Error);



在项目中的任何位置调用此 Web 服务

    WebserviceAmazon amazon = new WebserviceAmazon(getActivity(), imageName, "", 2);
    amazon.result(new WebserviceAmazon.WebServiceInterface<String, String>() 
        @Override
        public void success(String reslut) 

        

        @Override
        public void error(String Error) 

        
    );

    return totalPoints;

【讨论】:

此代码是否适用于视频?我可以用视频切换文件路径吗?【参考方案7】:

这是我将图像上传到 Amazon AWS S3 存储桶的代码 希望这对你有帮助 首先让我明确一些关键点 您可以从相机拍摄图像或从图库中选择图像,AWS 将图像存储为文件,因此首先您需要将图像存储到本地目录并获取图像路径,然后从该路径创建文件,之后您将能够上传该图像文件到 AWS。

首先您需要在 Oncreate

上添加配置
BasicAWSCredentials credentials = new BasicAWSCredentials(KEY,SECRET);
         s3 = new AmazonS3Client(credentials);
        s3.setRegion(Region.getRegion(Regions.US_EAST_1));

private void uploadFile() 

        verifyStoragePermissions(CustomCameraActivity.this);

        TransferUtility transferUtility =
                TransferUtility.builder()
                        .context(getApplicationContext())
                        .awsConfiguration(AWSMobileClient.getInstance().getConfiguration())
                        .s3Client(s3)
                        .build();

        TransferObserver uploadObserver= null;
        
        File file2 = FileUtils.getFile(CustomCameraActivity.this, storageImagePath);//here i am converting path to file ,,FileUtils.getFile is custom class
        
            uploadObserver = transferUtility.upload("your bucket name", imageNameWithoutExtension + ".jpg", file2);// imagenamewithoutExtension is actually the name that you want to store 

        uploadObserver.setTransferListener(new TransferListener() 

            @Override
            public void onStateChanged(int id, TransferState state) 
                if (TransferState.COMPLETED == state) 
                    Toast.makeText(getApplicationContext(), "Upload Completed!", Toast.LENGTH_SHORT).show();
                    uploadResourcesApi(uploadResoucesURL);
                    //imageFile.delete();
                    //file2.delete();
                 else if (TransferState.FAILED == state) 
                    //imageFile.delete();
                    //file2.delete();
                
            

            @Override
            public void onProgressChanged(int id, long bytesCurrent, long bytesTotal) 
                float percentDonef = ((float) bytesCurrent / (float) bytesTotal) * 100;
                int percentDone = (int) percentDonef;

                //tvFileName.setText("ID:" + id + "|bytesCurrent: " + bytesCurrent + "|bytesTotal: " + bytesTotal + "|" + percentDone + "%");
            

            @Override
            public void onError(int id, Exception ex) 
                ex.printStackTrace();
            

        );
     

这是 fileUtils 类

import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.util.Log;
import android.webkit.MimeTypeMap;



import java.io.File;
import java.io.FileFilter;
import java.text.DecimalFormat;
import java.util.Comparator;

/**
 * @version 2009-07-03
 * @author Peli
 * @version 2013-12-11
 * @author paulburke (ipaulpro)
 */
public class FileUtils 
    private FileUtils()  //private constructor to enforce Singleton pattern

    /** TAG for log messages. */
    static final String TAG = "FileUtils";
    private static final boolean DEBUG = false; // Set to true to enable logging

    public static final String MIME_TYPE_AUDIO = "audio/*";
    public static final String MIME_TYPE_TEXT = "text/*";
    public static final String MIME_TYPE_IMAGE = "image/*";
    public static final String MIME_TYPE_VIDEO = "video/*";
    public static final String MIME_TYPE_APP = "application/*";

    public static final String HIDDEN_PREFIX = ".";

    /**
     * Gets the extension of a file name, like ".png" or ".jpg".
     *
     * @param uri
     * @return Extension including the dot("."); "" if there is no extension;
     *         null if uri was null.
     */
    public static String getExtension(String uri) 
        if (uri == null) 
            return null;
        

        int dot = uri.lastIndexOf(".");
        if (dot >= 0) 
            return uri.substring(dot);
         else 
            // No extension.
            return "";
        
    

    /**
     * @return Whether the URI is a local one.
     */
    public static boolean isLocal(String url) 
        if (url != null && !url.startsWith("http://") && !url.startsWith("https://")) 
            return true;
        
        return false;
    

    /**
     * @return True if Uri is a MediaStore Uri.
     * @author paulburke
     */
    public static boolean isMediaUri(Uri uri) 
        return "media".equalsIgnoreCase(uri.getAuthority());
    

    /**
     * Convert File into Uri.
     *
     * @param file
     * @return uri
     */
    public static Uri getUri(File file) 
        if (file != null) 
            return Uri.fromFile(file);
        
        return null;
    

    /**
     * Returns the path only (without file name).
     *
     * @param file
     * @return
     */
    public static File getPathWithoutFilename(File file) 
        if (file != null) 
            if (file.isDirectory()) 
                // no file to be split off. Return everything
                return file;
             else 
                String filename = file.getName();
                String filepath = file.getAbsolutePath();

                // Construct path without file name.
                String pathwithoutname = filepath.substring(0,
                        filepath.length() - filename.length());
                if (pathwithoutname.endsWith("/")) 
                    pathwithoutname = pathwithoutname.substring(0, pathwithoutname.length() - 1);
                
                return new File(pathwithoutname);
            
        
        return null;
    

    /**
     * @return The MIME type for the given file.
     */
    public static String getMimeType(File file) 

        String extension = getExtension(file.getName());

        if (extension.length() > 0)
            return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension.substring(1));

        return "application/octet-stream";
    

    /**
     * @return The MIME type for the give Uri.
     */
    public static String getMimeType(Context context, Uri uri) 
        File file = new File(getPath(context, uri));
        return getMimeType(file);
    

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is @link LocalStorageProvider.
     * @author paulburke
     */
    public static boolean isLocalStorageDocument(Uri uri) 
        return LocalStorageProvider.AUTHORITY.equals(uri.getAuthority());
    

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is ExternalStorageProvider.
     * @author paulburke
     */
    public static boolean isExternalStorageDocument(Uri uri) 
        return "com.android.externalstorage.documents".equals(uri.getAuthority());
    

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is DownloadsProvider.
     * @author paulburke
     */
    public static boolean isDownloadsDocument(Uri uri) 
        return "com.android.providers.downloads.documents".equals(uri.getAuthority());
    

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is MediaProvider.
     * @author paulburke
     */
    public static boolean isMediaDocument(Uri uri) 
        return "com.android.providers.media.documents".equals(uri.getAuthority());
    

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is Google Photos.
     */
    public static boolean isGooglePhotosUri(Uri uri) 
        return "com.google.android.apps.photos.content".equals(uri.getAuthority());
    

    /**
     * Get the value of the data column for this Uri. This is useful for
     * MediaStore Uris, and other file-based ContentProviders.
     *
     * @param context The context.
     * @param uri The Uri to query.
     * @param selection (Optional) Filter used in the query.
     * @param selectionArgs (Optional) Selection arguments used in the query.
     * @return The value of the _data column, which is typically a file path.
     * @author paulburke
     */
    public static String getDataColumn(Context context, Uri uri, String selection,
                                       String[] selectionArgs) 

        Cursor cursor = null;
        final String column = "_data";
        final String[] projection = 
                column
        ;

        try 
            cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
                    null);
            if (cursor != null && cursor.moveToFirst()) 
                if (DEBUG)
                    DatabaseUtils.dumpCursor(cursor);

                final int column_index = cursor.getColumnIndexOrThrow(column);
                return cursor.getString(column_index);
            
         finally 
            if (cursor != null)
                cursor.close();
        
        return null;
    

    
    public static String getPath(final Context context, final Uri uri) 

        if (DEBUG)
            Log.d(TAG + " File -",
                    "Authority: " + uri.getAuthority() +
                            ", Fragment: " + uri.getFragment() +
                            ", Port: " + uri.getPort() +
                            ", Query: " + uri.getQuery() +
                            ", Scheme: " + uri.getScheme() +
                            ", Host: " + uri.getHost() +
                            ", Segments: " + uri.getPathSegments().toString()
            );

        final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;

        // DocumentProvider
        if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) 
            // LocalStorageProvider
            if (isLocalStorageDocument(uri)) 
                // The path is the id
                return DocumentsContract.getDocumentId(uri);
            
            // ExternalStorageProvider
            else if (isExternalStorageDocument(uri)) 
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

                if ("primary".equalsIgnoreCase(type)) 
                    return Environment.getExternalStorageDirectory() + "/" + split[1];
                

                // TODO handle non-primary volumes
            
            // DownloadsProvider
            else if (isDownloadsDocument(uri)) 

                final String id = DocumentsContract.getDocumentId(uri);
                final Uri contentUri = ContentUris.withAppendedId(
                        Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));

                return getDataColumn(context, contentUri, null, null);
            
            // MediaProvider
            else if (isMediaDocument(uri)) 
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

                Uri contentUri = null;
                if ("image".equals(type)) 
                    contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                 else if ("video".equals(type)) 
                    contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                 else if ("audio".equals(type)) 
                    contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                

                final String selection = "_id=?";
                final String[] selectionArgs = new String[] 
                        split[1]
                ;

                return getDataColumn(context, contentUri, selection, selectionArgs);
            
        
        // MediaStore (and general)
        else if ("content".equalsIgnoreCase(uri.getScheme())) 

            // Return the remote address
            if (isGooglePhotosUri(uri))
                return uri.getLastPathSegment();

            return getDataColumn(context, uri, null, null);
        
        // File
        else if ("file".equalsIgnoreCase(uri.getScheme())) 
            return uri.getPath();
        

        return null;
    

    
    public static File getFile(Context context, Uri uri) 
        if (uri != null) 
            String path = getPath(context, uri);
            if (path != null && isLocal(path)) 
                return new File(path);
            
        
        return null;
    

    
    public static String getReadableFileSize(int size) 
        final int BYTES_IN_KILOBYTES = 1024;
        final DecimalFormat dec = new DecimalFormat("###.#");
        final String KILOBYTES = " KB";
        final String MEGABYTES = " MB";
        final String GIGABYTES = " GB";
        float fileSize = 0;
        String suffix = KILOBYTES;

        if (size > BYTES_IN_KILOBYTES) 
            fileSize = size / BYTES_IN_KILOBYTES;
            if (fileSize > BYTES_IN_KILOBYTES) 
                fileSize = fileSize / BYTES_IN_KILOBYTES;
                if (fileSize > BYTES_IN_KILOBYTES) 
                    fileSize = fileSize / BYTES_IN_KILOBYTES;
                    suffix = GIGABYTES;
                 else 
                    suffix = MEGABYTES;
                
            
        
        return String.valueOf(dec.format(fileSize) + suffix);
    

    
    public static Bitmap getThumbnail(Context context, File file) 
        return getThumbnail(context, getUri(file), getMimeType(file));
    

    
    public static Bitmap getThumbnail(Context context, Uri uri) 
        return getThumbnail(context, uri, getMimeType(context, uri));
    

    
    public static Bitmap getThumbnail(Context context, Uri uri, String mimeType) 
        if (DEBUG)
            Log.d(TAG, "Attempting to get thumbnail");

        if (!isMediaUri(uri)) 
            Log.e(TAG, "You can only retrieve thumbnails for images and videos.");
            return null;
        

        Bitmap bm = null;
        if (uri != null) 
            final ContentResolver resolver = context.getContentResolver();
            Cursor cursor = null;
            try 
                cursor = resolver.query(uri, null, null, null, null);
                if (cursor.moveToFirst()) 
                    final int id = cursor.getInt(0);
                    if (DEBUG)
                        Log.d(TAG, "Got thumb ID: " + id);

                    if (mimeType.contains("video")) 
                        bm = MediaStore.Video.Thumbnails.getThumbnail(
                                resolver,
                                id,
                                MediaStore.Video.Thumbnails.MINI_KIND,
                                null);
                    
                    else if (mimeType.contains(FileUtils.MIME_TYPE_IMAGE)) 
                        bm = MediaStore.Images.Thumbnails.getThumbnail(
                                resolver,
                                id,
                                MediaStore.Images.Thumbnails.MINI_KIND,
                                null);
                    
                
             catch (Exception e) 
                if (DEBUG)
                    Log.e(TAG, "getThumbnail", e);
             finally 
                if (cursor != null)
                    cursor.close();
            
        
        return bm;
    

    
    public static Comparator<File> sComparator = new Comparator<File>() 
        @Override
        public int compare(File f1, File f2) 
            // Sort alphabetically by lower case, which is much cleaner
            return f1.getName().toLowerCase().compareTo(
                    f2.getName().toLowerCase());
        
    ;

   
    public static FileFilter sFileFilter = new FileFilter() 
        @Override
        public boolean accept(File file) 
            final String fileName = file.getName();
            // Return files only (not directories) and skip hidden files
            return file.isFile() && !fileName.startsWith(HIDDEN_PREFIX);
        
    ;

    
    public static FileFilter sDirFilter = new FileFilter() 
        @Override
        public boolean accept(File file) 
            final String fileName = file.getName();
            // Return directories only and skip hidden directories
            return file.isDirectory() && !fileName.startsWith(HIDDEN_PREFIX);
        
    ;

    
    public static Intent createGetContentIntent() 
        // Implicitly allow the user to select a particular kind of data
        final Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        // The MIME data type filter
        intent.setType("*/*");
        // Only return URIs that can be opened with ContentResolver
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        return intent;
    

那么你也需要这个类

public class LocalStorageProvider extends DocumentsProvider 

    public static final String AUTHORITY = "com.ianhanniballake.localstorage.documents";

    private final static String[] DEFAULT_ROOT_PROJECTION = new String[] 
            Root.COLUMN_ROOT_ID,
            Root.COLUMN_FLAGS, Root.COLUMN_TITLE, Root.COLUMN_DOCUMENT_ID, Root.COLUMN_ICON,
            Root.COLUMN_AVAILABLE_BYTES
    ;
    
    private final static String[] DEFAULT_DOCUMENT_PROJECTION = new String[] 
            Document.COLUMN_DOCUMENT_ID,
            Document.COLUMN_DISPLAY_NAME, Document.COLUMN_FLAGS, Document.COLUMN_MIME_TYPE,
            Document.COLUMN_SIZE,
            Document.COLUMN_LAST_MODIFIED
    ;

    @Override
    public Cursor queryRoots(final String[] projection) throws FileNotFoundException 
        
        final MatrixCursor result = new MatrixCursor(projection != null ? projection
                : DEFAULT_ROOT_PROJECTION);
        
        File homeDir = Environment.getExternalStorageDirectory();
        final MatrixCursor.RowBuilder row = result.newRow();
        // These columns are required
        row.add(Root.COLUMN_ROOT_ID, homeDir.getAbsolutePath());
        row.add(Root.COLUMN_DOCUMENT_ID, homeDir.getAbsolutePath());
        row.add(Root.COLUMN_TITLE, "Internal storage");
        row.add(Root.COLUMN_FLAGS, Root.FLAG_LOCAL_ONLY | Root.FLAG_SUPPORTS_CREATE);
        row.add(Root.COLUMN_ICON, R.drawable.ic_launcher_foreground);
        // These columns are optional
        row.add(Root.COLUMN_AVAILABLE_BYTES, homeDir.getFreeSpace());
        // Root.COLUMN_MIME_TYPE is another optional column and useful if you
        
        return result;
    

    @Override
    public String createDocument(final String parentDocumentId, final String mimeType,
                                 final String displayName) throws FileNotFoundException 
        File newFile = new File(parentDocumentId, displayName);
        try 
            newFile.createNewFile();
            return newFile.getAbsolutePath();
         catch (IOException e) 
            Log.e(LocalStorageProvider.class.getSimpleName(), "Error creating new file " + newFile);
        
        return null;
    

    @Override
    public AssetFileDescriptor openDocumentThumbnail(final String documentId, final Point sizeHint,
                                                     final CancellationSignal signal) throws FileNotFoundException 
        
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(documentId, options);
        final int targetHeight = 2 * sizeHint.y;
        final int targetWidth = 2 * sizeHint.x;
        final int height = options.outHeight;
        final int width = options.outWidth;
        options.inSampleSize = 1;
        if (height > targetHeight || width > targetWidth) 
            final int halfHeight = height / 2;
            final int halfWidth = width / 2;
           
            while ((halfHeight / options.inSampleSize) > targetHeight
                    || (halfWidth / options.inSampleSize) > targetWidth) 
                options.inSampleSize *= 2;
            
        
        options.inJustDecodeBounds = false;
        Bitmap bitmap = BitmapFactory.decodeFile(documentId, options);
        // Write out the thumbnail to a temporary file
        File tempFile = null;
        FileOutputStream out = null;
        try 
            tempFile = File.createTempFile("thumbnail", null, getContext().getCacheDir());
            out = new FileOutputStream(tempFile);
            bitmap.compress(Bitmap.CompressFormat.PNG, 90, out);
         catch (IOException e) 
            Log.e(LocalStorageProvider.class.getSimpleName(), "Error writing thumbnail", e);
            return null;
         finally 
            if (out != null)
                try 
                    out.close();
                 catch (IOException e) 
                    Log.e(LocalStorageProvider.class.getSimpleName(), "Error closing thumbnail", e);
                
        
        // It appears the Storage Framework UI caches these results quite
        // aggressively so there is little reason to
        // write your own caching layer beyond what you need to return a single
        // AssetFileDescriptor
        return new AssetFileDescriptor(ParcelFileDescriptor.open(tempFile,
                ParcelFileDescriptor.MODE_READ_ONLY), 0,
                AssetFileDescriptor.UNKNOWN_LENGTH);
    

    @Override
    public Cursor queryChildDocuments(final String parentDocumentId, final String[] projection,
                                      final String sortOrder) throws FileNotFoundException 
        // Create a cursor with either the requested fields, or the default
        // projection if "projection" is null.
        final MatrixCursor result = new MatrixCursor(projection != null ? projection
                : DEFAULT_DOCUMENT_PROJECTION);
        final File parent = new File(parentDocumentId);
        for (File file : parent.listFiles()) 
            // Don't show hidden files/folders
            if (!file.getName().startsWith(".")) 
                // Adds the file's display name, MIME type, size, and so on.
                includeFile(result, file);
            
        
        return result;
    

    @Override
    public Cursor queryDocument(final String documentId, final String[] projection)
            throws FileNotFoundException 
        // Create a cursor with either the requested fields, or the default
        // projection if "projection" is null.
        final MatrixCursor result = new MatrixCursor(projection != null ? projection
                : DEFAULT_DOCUMENT_PROJECTION);
        includeFile(result, new File(documentId));
        return result;
    

    private void includeFile(final MatrixCursor result, final File file)
            throws FileNotFoundException 
        final MatrixCursor.RowBuilder row = result.newRow();
        // These columns are required
        row.add(Document.COLUMN_DOCUMENT_ID, file.getAbsolutePath());
        row.add(Document.COLUMN_DISPLAY_NAME, file.getName());
        String mimeType = getDocumentType(file.getAbsolutePath());
        row.add(Document.COLUMN_MIME_TYPE, mimeType);
        int flags = file.canWrite() ? Document.FLAG_SUPPORTS_DELETE | Document.FLAG_SUPPORTS_WRITE
                : 0;
        // We only show thumbnails for image files - expect a call to
        // openDocumentThumbnail for each file that has
        // this flag set
        if (mimeType.startsWith("image/"))
            flags |= Document.FLAG_SUPPORTS_THUMBNAIL;
        row.add(Document.COLUMN_FLAGS, flags);
        // COLUMN_SIZE is required, but can be null
        row.add(Document.COLUMN_SIZE, file.length());
        // These columns are optional
        row.add(Document.COLUMN_LAST_MODIFIED, file.lastModified());
        // Document.COLUMN_ICON can be a resource id identifying a custom icon.
        // The system provides default icons
        // based on mime type
        // Document.COLUMN_SUMMARY is optional additional information about the
        // file
    

    @Override
    public String getDocumentType(final String documentId) throws FileNotFoundException 
        File file = new File(documentId);
        if (file.isDirectory())
            return Document.MIME_TYPE_DIR;
        // From FileProvider.getType(Uri)
        final int lastDot = file.getName().lastIndexOf('.');
        if (lastDot >= 0) 
            final String extension = file.getName().substring(lastDot + 1);
            final String mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
            if (mime != null) 
                return mime;
            
        
        return "application/octet-stream";
    

    @Override
    public void deleteDocument(final String documentId) throws FileNotFoundException 
        new File(documentId).delete();
    

    @Override
    public ParcelFileDescriptor openDocument(final String documentId, final String mode,
                                             final CancellationSignal signal) throws FileNotFoundException 
        File file = new File(documentId);
        final boolean isWrite = (mode.indexOf('w') != -1);
        if (isWrite) 
            return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_WRITE);
         else 
            return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
        
    

    @Override
    public boolean onCreate() 
        return true;
    

【讨论】:

以上是关于将图像从 Android 上传到 Amazon S3?的主要内容,如果未能解决你的问题,请参考以下文章

使用 amazon sdk 和存储桶策略从 ios 应用程序将图像上传到 amazon s3

将 base64 图像数据上传到 Amazon S3

如何在不使用 SDK 的情况下将文件从 Android 上传到 Amazon S3

将图像上传到 Amazon S3 时出现 NotAuthorizedException

如何将抓取的数据从 Scrapy 以 csv 或 json 格式上传到 Amazon S3?

使用 Amazon Educate Starter 账户将图像上传到 S3