Amazon S3バケットにファイルをアップロードしています。ファイルはアップロードされていますが、次の警告が表示されます。
警告:ストリームデータのコンテンツの長さは指定されていません。ストリームのコンテンツはメモリにバッファリングされ、メモリ不足エラーが発生する可能性があります。
そこで、次の行をコードに追加しました
metaData.setContentLength(IOUtils.toByteArray(input).length);
しかし、その後、私は次のメッセージを受け取りました。それが警告なのか、何なのかさえわかりません。
読み取られたデータの長さが予想とは異なります:dataLength = 0; expectedLength = 111992; includeSkipped = false; in.getClass()= class Sun.net.httpserver.FixedLengthInputStream; markSupported = false;マーク= 0; resetSinceLastMarked = false; markCount = 0; resetCount = 0
ContentLengthをInputSteamのmetaDataに設定するにはどうすればよいですか?どんな助けも大歓迎です。
IOUtils.toByteArray
を使用してデータを読み取ると、InputStreamが消費されます。 AWS APIが読み取ろうとするとき、長さはゼロです。
内容をバイト配列に読み取り、その配列をAPIにラップするInputStreamを提供します。
byte[] bytes = IOUtils.toByteArray(input);
metaData.setContentLength(bytes.length);
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
PutObjectRequest putObjectRequest = new PutObjectRequest(bucket, key, byteArrayInputStream, metadata);
client.putObject(putObjectRequest);
ByteBufferを使用することで、AWS SDKがすでに自動で行ったことを手動で行うだけです。それでもストリーム全体をメモリにバッファリングし、SDKから警告を生成する元のソリューションと同等の性能を発揮します。
たとえば、ファイルからストリームを作成するときなど、ストリームの長さを知る別の方法がある場合にのみ、メモリの問題を取り除くことができます。
void uploadFile(String bucketName, File file) {
try (final InputStream stream = new FileInputStream(file)) {
ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentLength(file.length());
s3client.putObject(
new PutObjectRequest(bucketName, file.getName(), stream, metadata)
);
}
}
速報! AWS SDK 2.0には、ファイルのアップロードのサポートが組み込まれています:
s3client.putObject(
(builder) -> builder.bucket(myBucket).key(file.getName()),
RequestBody.fromFile(file)
);
Content-Lengthを自動的かつ効率的に設定する文字列またはバッファを取得するRequestBody
メソッドもあります。別の種類のInputStreamを使用する場合にのみ、長さを自分で指定する必要がありますが、他のすべてのオプションを使用できるようになったため、このケースはよりまれになります。