2011-10-06 23 views

Trả lời

13

Trong khi IOUtils.copy()IOUtils.copyLarge() là tuyệt vời, tôi sẽ thích cách học cũ của Looping qua inputstream cho đến khi trở inputstream -1. Tại sao? Tôi đã sử dụng IOUtils.copy() trước đây nhưng có một trường hợp sử dụng cụ thể nếu tôi bắt đầu tải xuống một tệp lớn từ S3 và sau đó vì một số lý do nếu chuỗi đó bị gián đoạn, quá trình tải xuống sẽ không dừng lại và nó sẽ tiếp tục cho đến khi toàn bộ tệp đã được tải xuống.

Tất nhiên, điều này không liên quan gì đến S3, chỉ là thư viện IOUtils.

Vì vậy, tôi thích điều này:

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(); 

Lưu ý: Điều này cũng có nghĩa là bạn không cần thư viện bổ sung

+0

Tôi nên làm gì nếu tệp được nén? –

+0

Ngoại lệ OOB chỉ mục ném. –

+1

Hoặc đơn giản là làm 'Files.copy (trong, Paths.get ("/my/path/file.jpg "))' như @Jonik trả lời – Joan

4

lớp Các AmazonS3Client có phương pháp sau đây:

S3Object getObject(String bucketName, String key) 

Các S3Object trở có phương pháp ...

java.io.InputStream getObjectContent() 

đồi khế, đồi được nội dung đối tượng như một dòng suối. Tôi muốn sử dụng IOUtils từ Apache Commons như thế này:

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

+0

tôi nên làm gì nếu tập tin được gzip? –

17

Kể từ Java 7 (xuất bản trở lại trong tháng 7 năm 2011), có một cách tốt hơn : Files.copy() tiện ích từ java.util.nio.file.

Sao chép tất cả byte từ luồng đầu vào vào tệp.

Vì vậy, bạn cần khôngan external library cũng không lăn của riêng bạn byte array loops. Hai ví dụ bên dưới, cả hai đều sử dụng luồng đầu vào từ S3Object.getObjectContent().

InputStream in = s3Client.getObject("bucketName", "key").getObjectContent(); 

1) Viết vào một tập tin mới tại đường dẫn cụ thể:

Files.copy(in, Paths.get("/my/path/file.jpg")); 

2) Viết vào một tập tin tạm thời trong tmp mặc định vị trí của hệ thống:

File tmp = File.createTempFile("s3test", ""); 
Files.copy(in, tmp.toPath(), StandardCopyOption.REPLACE_EXISTING); 

(Nếu không chỉ định tùy chọn thay thế tệp hiện có, bạn sẽ nhận được FileAlreadyExistsException.)

Cũng lưu ý rằng getObjectContent() Javadocs mong bạn đóng input stream:

Nếu bạn lấy một S3Object, bạn nên đóng input stream này như sớm càng tốt, bởi vì nội dung đối tượng không được đệm trong bộ nhớ và phát trực tiếp từ Amazon S3. Hơn nữa, việc không đóng luồng này có thể khiến hồ bơi yêu cầu bị chặn.

Vì vậy, nên an toàn nhất để bao bọc mọi thứ trong cố gắng nắm bắt cuối cùng và thực hiện in.close(); trong khối cuối cùng.

Ở trên giả định rằng bạn sử dụng SDK chính thức từ Amazon (aws-java-sdk-s3).

+0

Đây là một sự chấp thuận tốt hơn nhiều so với cách thức lặp cũ thông qua các byte. – Joan

+0

Tôi thích làm 'Files.copy (trong, Paths.get ("/my/path/file.jpg "))'. Tốt hơn để có được con đường mà không đi qua File – Joan

+0

@Janan, điểm công bằng, được cập nhật! – Jonik

1

gì về một liner này sử dụng một TransferManager:

TransferManagerBuilder.defaultTransferManager 
    .download("bucket-name", "key", new File(".")) 
Các vấn đề liên quan