由于我已经搜索了很长时间以找到错误,我想在这里分享它,以防有人遇到同样的问题: 我已实现以下代码段以将数据上传到S3:
public class S3FileUploadHandler {
private static final String USER_META_DATA_KEY_MODIFIED = "last-modified";
private static final SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy");
private final AmazonS3Client s3;
private final TransferManager tm;
private final String bucketName = "myTestBucket";
...
public void run() {
File file = ... // retrieve file to upload
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
final String key = ... // some path on S3
final ObjectMetadata objectMetadata = buildObjectMetadata(file);
final PutObjectRequest req = new PutObjectRequest(bucketName, key, fis, objectMetadata);
final Upload upload = tm.upload(req);
upload.addProgressListener(new MyProgressListener(upload));
upload.waitForCompletion();
} catch (final AmazonServiceExceptionase) {
logger.debug("Couldn't put file {}. AmazonServiceException {}", file, ase);
logger.error("Couldn't put file {}. AmazonServiceException Error Message: {}", file, ase.getMessage());
logger.error("HTTP Status Code: " + ase.getStatusCode());
logger.error("AWS Error Code: " + ase.getErrorCode());
logger.error("Error Type: " + ase.getErrorType());
logger.error("Request ID: " + ase.getRequestId());
} catch (final Exception e) {
...
} finally {
if (fis != null) {
fis.close();
}
}
}
private ObjectMetadata buildObjectMetadata(final File file) {
final ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentLength(file.length());
final Date lastModifiedDate = new Date(file.lastModified());
final String dateStr = sdf.format(lastModifiedDate);
metadata.addUserMetadata(USER_META_DATA_KEY_MODIFIED, dateStr);
return metadata;
}
}
代码剪切将文件上传到AWS S3并保留文件的上次修改时间戳,我将此信息设置为用户元数据。
有时上面的代码有效,有时上传会中断,但会出现以下异常:
Couldn't put file C:\Temp\xyz.txt. AmazonServiceException Error Message: The request signature we calculated does not match the signature you provided. Check your key and signing method. (Service: Amazon S3; Status Code: 403; Error Code: SignatureDoesNotMatch; Request ID: B8BC3251B9C1A3F5)
HTTP Status Code: 403
AWS Error Code: SignatureDoesNotMatch
Error Type: Client
Request ID: B8BC3251B9C1A3F5
答案 0 :(得分:2)
上面代码中的错误是,SimpleDateFormat可能包含非ASCII字符。
E.g。德语区域设置上的最后修改日期可能是
Di Mär 21 10:29:00 MEZ 2017
用户定义的元数据是一组键值对。 Amazon S3以小写形式存储用户定义的元数据键。在使用SOAP和基于浏览器的POST上传时,每个键值对在使用REST和UTF-8时必须符合US-ASCII。
AWS可以在这里使用更好的Exception文本,但是根据上述信息,修复很简单:
private static final SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.US);
...导致(总是)接受的元数据字符串
Tue Mar 21 10:29:00 CET 2017