如何将S3对象写入文件?

Jas*_*son 15 java file-io amazon-s3 amazon-web-services

将S3对象(我有密钥)写入文件的最快方法是什么?我正在使用Java.

Jon*_*nik 28

Java 7(2011年7月发布)以来,有一种更好的方法:Files.copy()实用程序来自java.util.nio.file.

将输入流中的所有字节复制到文件.

因此,您既不 需要外部库也不需要滚动自己的字节数组循环.下面两个例子,两个都使用来自的输入流S3Object.getObjectContent().

InputStream in = s3Client.getObject("bucketName", "key").getObjectContent();
Run Code Online (Sandbox Code Playgroud)

1)写入指定路径的新文件:

Files.copy(in, Paths.get("/my/path/file.jpg"));
Run Code Online (Sandbox Code Playgroud)

2)写入系统默认tmp位置的临时文件:

File tmp = File.createTempFile("s3test", "");
Files.copy(in, tmp.toPath(), StandardCopyOption.REPLACE_EXISTING);
Run Code Online (Sandbox Code Playgroud)

(如果没有指定替换现有文件的选项,您将得到一个FileAlreadyExistsException.)

另请注意,getObjectContent()Javadocs敦促您关闭输入流:

如果检索S3Object,则应尽快关闭此输入流,因为对象内容不会缓存在内存中,而是直接从Amazon S3流式传输.此外,无法关闭此流可能会导致请求池被阻止.

因此,最好将所有内容包装在try-catch-finally中,并in.close();在finally块中执行.

以上假设您使用Amazon(aws-java-sdk-s3)的官方SDK .

  • 如果你不需要赶上考虑[尝试使用资源](https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html) (2认同)

sri*_*eak 16

虽然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();
Run Code Online (Sandbox Code Playgroud)

注意:这也意味着您不需要其他库


Jon*_*han 7

AmazonS3Client类具有以下方法:

S3Object getObject(String bucketName, String key)
Run Code Online (Sandbox Code Playgroud)

返回的S3Object有方法......

java.io.InputStream getObjectContent()
Run Code Online (Sandbox Code Playgroud)

..which将对象内容作为流获取.我会像这样使用Apache Commons的IOUtils:

IOUtils.copy(s3Object.getObjectContent(), new FileOutputStream(new File(filepath)));