如何在将文件上传到Amazon s3时添加自定义标题字段

时间:2016-06-14 09:47:25

标签: android amazon-web-services amazon-s3

我需要在Amazons3中存储多媒体文件。

我使用以下代码上传文件。

方法1:

import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.StrictMode;
import android.util.Log;

import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.AbortMultipartUploadRequest;
import com.amazonaws.services.s3.model.CannedAccessControlList;
import com.amazonaws.services.s3.model.CompleteMultipartUploadRequest;
import com.amazonaws.services.s3.model.CompleteMultipartUploadResult;
import com.amazonaws.services.s3.model.InitiateMultipartUploadRequest;
import com.amazonaws.services.s3.model.InitiateMultipartUploadResult;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.services.s3.model.PartETag;
import com.amazonaws.services.s3.model.ProgressEvent;
import com.amazonaws.services.s3.model.ProgressListener;
import com.amazonaws.services.s3.model.UploadPartRequest;
import com.amazonaws.services.s3.model.UploadPartResult;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

public class AmazonUploader {

    private static final long MIN_DEFAULT_PART_SIZE = 5 * 1024 * 1024;

    private static final String TAG = "AmazonUploader";
    private static final String PREFS_NAME = "preferences_simpl3r";
    private static final String PREFS_UPLOAD_ID = "_uploadId";
    private static final String PREFS_ETAGS = "_etags";
    private static final String PREFS_ETAG_SEP = "~~";

    private AmazonS3Client s3Client;
    private String s3bucketName;
    private String s3key;
    private File file;

    private SharedPreferences prefs;
    private long partSize = MIN_DEFAULT_PART_SIZE;
    private UploadProgressListener progressListener;
    private long bytesUploaded = 0;
    private boolean userInterrupted = false;
    private boolean userAborted = false;

    public AmazonUploader(Context context, AmazonS3Client s3Client, String s3bucketName, String s3key, File file) {
        if (android.os.Build.VERSION.SDK_INT > 9) {
            StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
            StrictMode.setThreadPolicy(policy);
        }
        this.s3Client = s3Client;
        this.s3key = s3key;
        this.s3bucketName = s3bucketName;
        this.file = file;
        prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
    }

    /**
     * Initiate a multipart file upload to Amazon S3
     *
     * @return the URL of a successfully uploaded file
     */
    public String start() {

        // initialize
        List<PartETag> partETags = new ArrayList<PartETag>();
        final long contentLength = file.length();
        long filePosition = 0;
        int startPartNumber = 1;

        userInterrupted = false;
        userAborted = false;
        bytesUploaded = 0;

        // check if we can resume an incomplete download
        String uploadId = getCachedUploadId();

        if (uploadId != null) {
            // we can resume the download
            Log.i(TAG, "resuming upload for " + uploadId);

            // get the cached etags
            List<PartETag> cachedEtags = getCachedPartEtags();
            partETags.addAll(cachedEtags);

            // calculate the start position for resume
            startPartNumber = cachedEtags.size() + 1;
            filePosition = (startPartNumber - 1) * partSize;
            bytesUploaded = filePosition;

            Log.i(TAG, "resuming at part " + startPartNumber + " position " + filePosition);

        } else {
            // initiate a new multi part upload
            Log.i(TAG, "initiating new upload");

            InitiateMultipartUploadRequest initRequest = new InitiateMultipartUploadRequest(s3bucketName, s3key);
//            ObjectMetadata obj = new ObjectMetadata();
//            obj.setContentType("image/jpeg");
//            obj.setHeader(Constants.APP_HEADER_REFERER, Constants.APP_REFERER_URL);
//            initRequest.setObjectMetadata(obj);


            configureInitiateRequest(initRequest);
            InitiateMultipartUploadResult initResponse = s3Client.initiateMultipartUpload(initRequest);
            uploadId = initResponse.getUploadId();

        }

        final AbortMultipartUploadRequest abortRequest = new AbortMultipartUploadRequest(s3bucketName, s3key, uploadId);

        for (int k = startPartNumber; filePosition < contentLength; k++) {

            long thisPartSize = Math.min(partSize, (contentLength - filePosition));

            Log.i(TAG, "starting file part " + k + " with size " + thisPartSize);

            UploadPartRequest uploadRequest = new UploadPartRequest().withBucketName(s3bucketName)
                    .withKey(s3key).withUploadId(uploadId)
                    .withPartNumber(k).withFileOffset(filePosition).withFile(file)
                    .withPartSize(thisPartSize);

            ProgressListener s3progressListener = new ProgressListener() {
                public void progressChanged(ProgressEvent progressEvent) {

                    // bail out if user cancelled
                    // TODO calling shutdown too brute force?
                    if (userInterrupted) {
                        s3Client.shutdown();
                        throw new UploadIterruptedException("User interrupted");
                    } else if (userAborted) {
                        // aborted requests cannot be resumed, so clear any cached etags
                        clearProgressCache();
                        s3Client.abortMultipartUpload(abortRequest);
                        s3Client.shutdown();
                    }

                    bytesUploaded += progressEvent.getBytesTransfered();

                    //Log.d(TAG, "bytesUploaded=" + bytesUploaded);

                    // broadcast progress
                    float fpercent = ((bytesUploaded * 100) / contentLength);
                    int percent = Math.round(fpercent);
                    if (progressListener != null) {
                        progressListener.progressChanged(progressEvent, bytesUploaded, percent);
                    }

                }
            };

            uploadRequest.setProgressListener(s3progressListener);

            UploadPartResult result = s3Client.uploadPart(uploadRequest);
            partETags.add(result.getPartETag());

            // cache the part progress for this upload
            if (k == 1) {
                initProgressCache(uploadId);
            }
            // store part etag
            cachePartEtag(result);

            filePosition += thisPartSize;
        }

        CompleteMultipartUploadRequest compRequest = new CompleteMultipartUploadRequest(
                s3bucketName, s3key, uploadId,
                partETags);

        CompleteMultipartUploadResult result = s3Client.completeMultipartUpload(compRequest);
        bytesUploaded = 0;

        Log.i(TAG, "upload complete for " + uploadId);

        clearProgressCache();

        return result.getLocation();

    }

    private String getCachedUploadId() {
        return prefs.getString(s3key + PREFS_UPLOAD_ID, null);
    }

    private List<PartETag> getCachedPartEtags() {
        List<PartETag> result = new ArrayList<PartETag>();
        // get the cached etags
        ArrayList<String> etags = SharedPreferencesUtils.getStringArrayPref(prefs, s3key + PREFS_ETAGS);
        for (String etagString : etags) {
            String partNum = etagString.substring(0, etagString.indexOf(PREFS_ETAG_SEP));
            String partTag = etagString.substring(etagString.indexOf(PREFS_ETAG_SEP) + 2, etagString.length());

            PartETag etag = new PartETag(Integer.parseInt(partNum), partTag);
            result.add(etag);
        }
        return result;
    }

    private void cachePartEtag(UploadPartResult result) {
        String serialEtag = result.getPartETag().getPartNumber() + PREFS_ETAG_SEP + result.getPartETag().getETag();
        ArrayList<String> etags = SharedPreferencesUtils.getStringArrayPref(prefs, s3key + PREFS_ETAGS);
        etags.add(serialEtag);
        SharedPreferencesUtils.setStringArrayPref(prefs, s3key + PREFS_ETAGS, etags);
    }

    private void initProgressCache(String uploadId) {
        // store uploadID
        Editor edit = prefs.edit().putString(s3key + PREFS_UPLOAD_ID, uploadId);
        AmazonSharedPreferencesCompact.apply(edit);
        // create empty etag array
        ArrayList<String> etags = new ArrayList<String>();
        SharedPreferencesUtils.setStringArrayPref(prefs, s3key + PREFS_ETAGS, etags);
    }

    private void clearProgressCache() {
        // clear the cached uploadId and etags
        Editor edit = prefs.edit();
        edit.remove(s3key + PREFS_UPLOAD_ID);
        edit.remove(s3key + PREFS_ETAGS);
        AmazonSharedPreferencesCompact.apply(edit);
    }

    public void interrupt() {
        userInterrupted = true;
    }

    public void abort() {
        userAborted = true;
    }

    /**
     * Override to configure the multipart upload request.
     * <p/>
     * By default uploaded files are publicly readable.
     *
     * @param initRequest S3 request object for the file to be uploaded
     */
    protected void configureInitiateRequest(InitiateMultipartUploadRequest initRequest) {
        initRequest.setCannedACL(CannedAccessControlList.PublicRead);
        ObjectMetadata obj = new ObjectMetadata();
        obj.setContentType("image/jpeg");
        obj.setHeader(Constants.APP_HEADER_REFERER, Constants.APP_REFERER_URL);
        initRequest.withObjectMetadata(obj);
    }

    public void setPrefs(SharedPreferences prefs) {
        this.prefs = prefs;
    }

    public long getPartSize() {
        return partSize;
    }

    public void setPartSize(long partSize) {
        if (partSize < MIN_DEFAULT_PART_SIZE) {
            throw new IllegalStateException("Part size is less than S3 minimum of " + MIN_DEFAULT_PART_SIZE);
        } else {
            this.partSize = partSize;
        }
    }

    public void setProgressListener(UploadProgressListener progressListener) {
        this.progressListener = progressListener;
    }

    public interface UploadProgressListener {
        public void progressChanged(ProgressEvent progressEvent, long bytesUploaded, int percentUploaded);
    }

}

方法2:

TransferObserver transferObserver = transferUtility.upload(
        Constants.S3_BUCKET_NAME,     /* The bucket to upload to */
        fileName,    /* The key for the uploaded object */
        new File(imagePath),       /* The file where the data to upload exists */
        objectMetadata);

transferObserverListener(transferObserver);

在这两种方法中我都收到了以下错误

 com.amazonaws.services.s3.model.AmazonS3Exception: Forbidden (Service: Amazon S3; Status Code: 403; Error Code: 403 Forbidden; Request... 

这里我必须传递客户标头参数,所以我添加如下

 ObjectMetadata objectMetadata = new ObjectMetadata();
        HashMap<String, String> mMetaMap = new HashMap<String, String>();
        mMetaMap.put("content-type", "image/jpeg");
        mMetaMap.put(Constants.APP_HEADER_REFERER, Constants.APP_REFERER_URL);
        objectMetadata.setUserMetadata(mMetaMap);

但我仍然遇到了上述错误。

我是否以正确的方式传递标头参数,或者我需要进行更改。请就此提出建议。感谢

0 个答案:

没有答案