1

我正在尝试将文件写入 S3,但遇到了一个奇怪的问题。如果我不设置 ContentLength,则文件上传运行良好。而且我仍然可以设置MD5。但是,如果我确实尝试设置内容长度(这是一个最佳实践),那么我会在写入时收到超时错误,大概是因为我发送 S3 的大小和实际大小不同(所以它认为它仍然是等待内容。)

这是我的代码。

private PutObjectResult storeFile(String key, InputStream content) {

    PutObjectResult result = null;
    if (content != null) {
        PutObjectRequest request;
        try {
            ObjectMetadata metaData = new ObjectMetadata();
            metaData.setContentLength(IOUtils.toByteArray(content).length);
            byte[] resultByte = DigestUtils.md5(content);
            String streamMD5 = new String(Base64.encodeBase64(resultByte));
            metaData.setContentMD5(streamMD5);
            request = new PutObjectRequest(S3_BUCKET,
                    key, content, metaData);
            result = client.putObject(request);
        } catch (AmazonS3Exception e){
            LOG.error("Error writing to S3", e);
            throw new RuntimeException("Error writing to S3", e);
        } catch (IOException e) {
            LOG.error("IO exception creating the MD5", e);
            throw new RuntimeException("Error creating an MD5", e);
        }



    }
    return result;
}

我有两组代码调用它。一种是从输出流中获取数据并将其转换为输入流

        ByteArrayOutputStream stream = engine.render(template.getContent(), data);
    InputStream content = new ByteArrayInputStream(stream.toByteArray());
    doc.setContent(content);

另一种是采用 Base64 编码的字符串,将其解编码为 byte[],然后将其转换为 InputStream。

            String content = template.getFileContent();
        byte[] contentBytes = Base64.decodeBase64(content);
        PutObjectResult result = this.storeFile(key,
                new ByteArrayInputStream(contentBytes));

第一种方法有效(我们从 OutputStream 开始,但我们从 Base64 编码字符串开始的方法没有。

我得到的错误是

AmazonS3Exception: Status Code: 400, AWS Service: Amazon S3, AWS Request ID: 018D75871D4E4F56, AWS Error Code: RequestTimeout, AWS Error Message: Your socket connection to the server was not read from or written to within the timeout period. Idle connections will be closed., S3 Extended Request ID: 04guESsxeumTi3Bh0/SfL2q8rNwDq6PObGq12imLwVZxkZs4X+8outdlYAiHr47+

关于可能导致这种情况的任何想法?

4

1 回答 1

3

问题是您正在阅读content三(!)次。这里两次:

metaData.setContentLength(IOUtils.toByteArray(content).length);
byte[] resultByte = DigestUtils.md5(content);

第一行从流中获取所有内容并使用 正确设置其长度setContentLength()。第二行得到一个空流。此行再次获得一个空流:

result = client.putObject(request);

只需将其读入字节数组一次,关闭流并操作数组。

于 2013-06-03T19:28:17.627 回答