Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/386.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 上载到AWS S3时签名不匹配_Java_Exception_Amazon S3_Metadata - Fatal编程技术网

Java 上载到AWS S3时签名不匹配

Java 上载到AWS S3时签名不匹配,java,exception,amazon-s3,metadata,Java,Exception,Amazon S3,Metadata,由于我已经搜索了很长时间来查找bug,我想在这里分享它,以防有人遇到相同的问题: 我已经实现了以下代码片段来将数据上载到S3: 公共类S3FileUploadHandler{ 私有静态最终字符串用户\u元数据\u密钥\u MODIFIED=“last MODIFIED”; 专用静态最终SimpleDataFormat sdf=新SimpleDataFormat(“EEE MMM dd HH:mm:ss zzz yyyy”); 私有最终AmazonS3客户s3; 私人最终转让经理tm; 私有最终字

由于我已经搜索了很长时间来查找bug,我想在这里分享它,以防有人遇到相同的问题: 我已经实现了以下代码片段来将数据上载到S3:

公共类S3FileUploadHandler{
私有静态最终字符串用户\u元数据\u密钥\u MODIFIED=“last MODIFIED”;
专用静态最终SimpleDataFormat sdf=新SimpleDataFormat(“EEE MMM dd HH:mm:ss zzz yyyy”);
私有最终AmazonS3客户s3;
私人最终转让经理tm;
私有最终字符串bucketName=“myTestBucket”;
...
公开募捐{
File File=…//检索要上载的文件
FileInputStream fis=null;
试一试{
fis=新文件输入流(文件);
final String key=…//S3上的某个路径
最终ObjectMetadata ObjectMetadata=buildObjectMetadata(文件);
最终PutObjectRequest req=新的PutObjectRequest(bucketName、键、fis、objectMetadata);
最终上传=自动上传(req);
upload.addProgressListener(新的MyProgressListener(upload));
upload.waitForCompletion();
}捕获(最终AmazonServiceExceptionase){
debug(“无法放置文件{}.AmazonServiceException{}”,文件,ase);
logger.error(“无法放置文件{}.AmazonServiceException错误消息:{}”,文件,ase.getMessage());
logger.error(“HTTP状态代码:+ase.getStatusCode());
logger.error(“AWS错误代码:+ase.getErrorCode());
logger.error(“错误类型:+ase.getErrorType());
logger.error(“请求ID:+ase.getRequestId());
}捕获(最终异常e){
...
}最后{
如果(fis!=null){
fis.close();
}
}
}
私有对象元数据buildObjectMetadata(最终文件){
最终ObjectMetadata=新ObjectMetadata();
setContentLength(file.length());
最终日期lastModifiedDate=新日期(file.lastModified());
最终字符串dateStr=sdf.format(lastModifiedDate);
addUserMetadata(用户\元数据\数据\密钥\修改,dateStr);
返回元数据;
}
}
截取的代码将文件上传到AWS S3,为了保留文件最后修改的时间戳,我将此信息设置为用户元数据

有时上述代码起作用,有时上载中断,但以下情况除外:

无法放置文件C:\Temp\xyz.txt。AmazonServiceException错误消息:我们计算的请求签名与您提供的签名不匹配。检查您的密钥和签名方法。(服务:Amazon S3;状态代码:403;错误代码:SignatureDesNotMatch;请求ID:B8BC3251B9C1A3F5)
HTTP状态代码:403
AWS错误代码:SignatureDesNotMatch
错误类型:客户端
请求ID:B8BC3251B9C1A3F5

上面代码中的错误是,SimpleDataFormat可能包含非ASCII字符

例如,德国地区的最后修改日期可能为

Di Mär 21 10:29:00 MEZ 2017
国家

用户定义的元数据是一组键值对。AmazonS3以小写形式存储用户定义的元数据键。当使用REST时,每个键值对必须符合US-ASCII,当使用SOAP或基于浏览器的POST上传时,每个键值对必须符合UTF-8

AWS确实可以在这里处理更好的异常文本,但有了上述信息,修复非常简单:

private static final SimpleDateFormat sdf=新的SimpleDateFormat(“EEE-MMM-dd-HH:mm:ss-zzz-yyyy”,Locale.US);
…产生(始终)可接受的元数据字符串

2017年3月21日星期二10:29:00 CET

感谢您的贡献。不幸的是,返回了一个详细的异常,但是SDK对您隐藏了它。令人惊讶的是,这个异常(我发现是因为我编写了自己的库而没有使用SDK)揭示了S3中的一个问题(或它前面的某个东西),如果在签名请求时将unicode字符替换为
,这实际上是可行的。(!?)生成这样一个故意错误的签名实际上允许存储utf8元数据。然后,如果查看对象的元数据,控制台会抛出一个异常——但它在下载时就在那里。