java - AWS Java SDK 上传元数据时出错

标签 java amazon-web-services amazon-s3

我正在尝试将文件上传到 S3 容器,在上传之前,我正在设置文件的元数据。上传失败并显示签名不匹配的错误。下面是我正在使用的代码:

public URL send(File f, HashMap<String,String> metadata, String type) throws Exception {
    String path = type+"/"+f.getName();

    InitiateMultipartUploadRequest req = new InitiateMultipartUploadRequest(container, secretKey).withKey(path);
    req.setCannedACL(CannedAccessControlList.AuthenticatedRead);

    if (metadata != null) {
        ObjectMetadata objectMetadata = new ObjectMetadata();
        Set<String> keys = metadata.keySet();
        Iterator<String> i = keys.iterator();
        while (i.hasNext()) {
            String key = i.next();
            objectMetadata.addUserMetadata(key, metadata.get(key));
        }
        req.setObjectMetadata(objectMetadata);
    }


    InitiateMultipartUploadResult res = s3client.initiateMultipartUpload(req);

    String uploadId = res.getUploadId();
    long fileSize = f.length();
    //check the size doesn't exceed max limit
    if (fileSize > MAX_OBJ_SIZE) {
        throw new Exception("Object size exceeds repository limit");
    }
    long chunkSize = 1024 * 1024 * 16;
    int chunks = (int) (fileSize/chunkSize + 2);
    List<PartETag> chunkList = new ArrayList<PartETag>();
    long pos = 0; 
    try {
        for (int i = 1; i < chunks; i++) {

            if ((chunks -i) < 2) {
                chunkSize = fileSize - pos;
            }

            UploadPartRequest upReq = new UploadPartRequest()
                    .withBucketName(container).withKey(path)
                    .withUploadId(uploadId).withPartNumber(i)
                    .withFileOffset(pos).withFile(f)
                    .withPartSize(chunkSize);

            PartETag pTag = null;
            // repeat the upload until it succeeds.
            boolean repeat;  
            do {
                repeat = false;  // reset switch
                try {
                    // Upload part and add response to our list.
                    pTag =   s3client.uploadPart(upReq).getPartETag(); 
                } 
                catch (Exception ex) {
                    repeat = true; // repeat
                }
            } while (repeat);

            chunkList.add(pTag);
            pos = pos + chunkSize;
        }
        CompleteMultipartUploadRequest compl = new CompleteMultipartUploadRequest(
                container, secretKey, uploadId, chunkList).withKey(path);
        CompleteMultipartUploadResult  complRes = s3client.completeMultipartUpload(compl);
        return new URL(URLDecoder.decode(complRes.getLocation(), "UTF-8"));
    }
    catch (Exception ex) {
        s3client.abortMultipartUpload(new AbortMultipartUploadRequest(container, 
                secretKey, uploadId));
        throw new Exception("File upload error: "+ex.toString());
    }
}

下面是我得到的错误:

 com.amazonaws.services.s3.model.AmazonS3Exception: Status Code: 403, AWS Service: Amazon S3, AWS Request ID: 0805716BBD0662AB, AWS Error Code: SignatureDoesNotMatch, AWS Error Message: The request signature we calculated does not match the signature you provided. Check your key and signing method., S3 Extended Request ID: wNAzUyrLZgWCazZFe3KpMHO0uh0FM5FF7fiwBzN1A2YDEYS5hKZBYh5nWSjIhnhG
at com.amazonaws.http.AmazonHttpClient.handleErrorResponse(AmazonHttpClient.java:767)
at com.amazonaws.http.AmazonHttpClient.executeHelper(AmazonHttpClient.java:414)
at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:228)
at com.amazonaws.services.s3.AmazonS3Client.invoke(AmazonS3Client.java:3316)
at com.amazonaws.services.s3.AmazonS3Client.initiateMultipartUpload(AmazonS3Client.java:2401)
at net.timbusproject.storage.awss3.S3Client.send(S3Client.java:134)

发生错误的 S3Client.java 中的第 134 行是:

 InitiateMultipartUploadResult res = s3client.initiateMultipartUpload(req);

如果我没有附加任何元数据,上传工作正常。即,如果我评论以下行,则上传有效:

 req.setObjectMetadata(objectMetadata);

我无法弄清楚设置元数据后请求失败的原因。我是否遗漏了上传过程中的任何步骤?

最佳答案

我能够通过对元数据键和值进行 URL 编码来解决这个问题。

objectMetadata.addUserMetadata(URLEncoder.encode(key, "UTF-8"), URLEncoder.encode(metadata.get(key),"UTF-8"));

显然,元数据似乎有一些令人反感的字符,这些字符会干扰 AWS 调用。此解决方法将使上传无误地完成并更新元数据,但字符串仍保持 url 编码,这可能会在以后出现问题。

关于java - AWS Java SDK 上传元数据时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23239304/

相关文章:

java - Google AppEngine 不显示网页

amazon-web-services - 将 EC2 AMI 从一个区域复制到 AWS 中的另一个区域

jquery - 使用 jQuery fileupload 插件直接上传到 Amazon S3

java - Jersey 1.x 和 Tomcat : how to register a ContainerRequestFilter programmatically, 即没有 web.xml?

java - JTable 选择和 TableModel

java - Java 中的复选框列表?

amazon-web-services - AWS 服务之间的通信(通过 ARN 定位)是否始终使用 SSL?

amazon-web-services - DynamoDB getItem - 当项目为 N 时,预期项目为 S

python-2.7 - 如何使用 AWS Lambda python 创建 S3 存储桶?

amazon-web-services - 用于 S3 完全访问的 Cloudformation AWS::IAM::Policy 的正确语法是什么