S3オブジェクト(私がキーを持っている)をファイルに書き込む最も速い方法は何ですか?私はJavaを使用しています。
IOUtils.copy()
とIOUtils.copyLarge()
は素晴らしいですが、入力ストリームが-1を返すまで、入力ストリームをループする古い方法をお勧めします。どうして?以前にIOUtils.copy()を使用しましたが、S3から大きなファイルのダウンロードを開始した後、何らかの理由でそのスレッドが中断された場合、ダウンロードが停止せず、ダウンロードが停止せず、ファイル全体がダウンロードされました。
もちろん、これはS3とは関係がなく、IOUtilsライブラリだけです。
だから、私はこれを好む:
InputStream in = s3Object.getObjectContent();
byte[] buf = new byte[1024];
OutputStream out = new FileOutputStream(file);
while( (count = in.read(buf)) != -1)
{
if( Thread.interrupted() )
{
throw new InterruptedException();
}
out.write(buf, 0, count);
}
out.close();
in.close();
注:これは、追加のライブラリが必要ないことも意味します
Java 7(2011年7月に公開)なので、より良い方法があります: Files.copy()
ユーティリティfrom _Java.util.nio.file
_ 。
入力ストリームからファイルにすべてのバイトをコピーします。
したがって、どちらも外部ライブラリ も必要ありません バイト配列ループ も必要ありません。以下の2つの例では、どちらもS3Object.getObjectContent()
からの入力ストリームを使用しています。
_InputStream in = s3Client.getObject("bucketName", "key").getObjectContent();
_
1)指定されたパスで新しいファイルに書き込みます:
_Files.copy(in, Paths.get("/my/path/file.jpg"));
_
2)システムのデフォルトのtmpの場所にある一時ファイルに書き込みます。
_File tmp = File.createTempFile("s3test", "");
Files.copy(in, tmp.toPath(), StandardCopyOption.REPLACE_EXISTING);
_
(既存のファイルを置き換えるオプションを指定しないと、FileAlreadyExistsException
を取得します。)
また、 getObjectContent()
Javadocs 入力ストリームを閉じるように促します:
S3Objectを取得する場合、オブジェクトのコンテンツはメモリにバッファリングされず、Amazon S3から直接ストリーミングされるため、この入力ストリームをできるだけ早く閉じる必要があります。さらに、このストリームを閉じることができないと、リクエストプールがブロックされる可能性があります。
したがって、すべてをtry-catch-finallyでラップし、finallyブロックでin.close();
を実行するのが最も安全なはずです。
上記は、Amazonの公式SDKを使用していることを前提としています( _aws-Java-sdk-s3
_ )。
AmazonS3Clientクラスには次のメソッドがあります。
_S3Object getObject(String bucketName, String key)
_
返されるS3Objectにはメソッドがあります...
_Java.io.InputStream getObjectContent()
_
..オブジェクトコンテンツをストリームとして取得します。次のように、ApacheCommonsのIOUtilsを使用します。
IOUtils.copy(s3Object.getObjectContent(), new FileOutputStream(new File(filepath)));
TransferManagerを使用したこの1つのライナーはどうですか?
TransferManagerBuilder.defaultTransferManager
.download("bucket-name", "key", new File("."))