2010-06-26 41 views
10

VớiLàm cách nào để trích xuất một tệp đơn lẻ từ tệp lưu trữ từ xa?

  1. URL của một kho lưu trữ (ví dụ như một file zip)
  2. Họ và tên (bao gồm cả đường dẫn) của một tập tin bên trong kho lưu trữ mà

Tôi đang tìm kiếm một cách (tốt nhất là trong Java) để tạo bản sao cục bộ của tệp đó, mà không cần tải xuống toàn bộ lưu trữ đầu tiên.

Từ sự hiểu biết của tôi (có giới hạn), điều đó có thể xảy ra, mặc dù tôi không biết cách thực hiện điều đó. Tôi đã sử dụng TrueZip, vì nó có vẻ hỗ trợ nhiều loại lưu trữ khác nhau, nhưng tôi có nghi ngờ về khả năng hoạt động của nó theo cách như vậy. Có ai có kinh nghiệm với loại điều đó không?

CHỈNH SỬA: cũng có thể làm điều đó với tarball và tarball được nén cũng rất quan trọng đối với tôi.

Trả lời

8

Vâng, ở mức tối thiểu, bạn phải tải xuống phần lưu trữ lên đến và bao gồm dữ liệu đã nén của tệp bạn muốn trích xuất. Điều đó gợi ý giải pháp sau: mở URLConnection vào kho lưu trữ, lấy luồng đầu vào của nó, quấn nó vào một số ZipInputStream và liên tục gọi getNextEntry()closeEntry() để lặp qua tất cả các mục trong tệp cho đến khi bạn đạt được mục bạn muốn. Sau đó, bạn có thể đọc dữ liệu của nó bằng cách sử dụng ZipInputStream.read(...).

mã Java sẽ giống như thế này:

URL url = new URL("http://example.com/path/to/archive"); 
ZipInputStream zin = new ZipInputStream(url.getInputStream()); 
ZipEntry ze = zin.getNextEntry(); 
while (!ze.getName().equals(pathToFile)) { 
    zin.closeEntry(); // not sure whether this is necessary 
    ze = zin.getNextEntry(); 
} 
byte[] bytes = new byte[ze.getSize()]; 
zin.read(bytes); 

Đây là, tất nhiên, chưa được kiểm tra.

+0

Cảm ơn bạn; điều này dường như làm việc tốt (thanh lỗi nhỏ), mặc dù tiếc là điều này không thể xử lý bất cứ điều gì nhưng lưu trữ zip. – Oak

+3

Vâng, tại sao bạn nghĩ nó được gọi là 'ZipInputStream'? ;-) Nếu bạn nhìn xung quanh internet, bạn có thể tìm thấy một 'TarInputStream' mà bạn có thể sử dụng gần như giống nhau - hoặc nếu không, bạn có thể viết của riêng bạn. Nó sẽ dễ dàng bởi vì các tập tin tar không được nén, về cơ bản nó chỉ là một tiêu đề cho mỗi tập tin theo sau bởi dữ liệu tập tin. (Wikipedia có một mô tả về định dạng) Đối với lưu trữ tar gzipped, thư viện chuẩn của Java có một 'GZIPInputStream' bạn có thể sử dụng cùng với luồng tar. –

+0

Thật vậy, Apache có một [TarInputStream] (http://javadoc.haefelinger.it/org.apache.ant/1.7.1/org/apache/tools/tar/TarInputStream.html) class :) – Oak

0

Tôi không chắc chắn có cách nào để rút ra một tệp duy nhất từ ​​một tệp ZIP mà không tải xuống toàn bộ nội dung trước không. Nhưng, nếu bạn là người duy nhất lưu trữ các tập tin ZIP, bạn có thể tạo ra một servlet Java mà đọc các tập tin ZIP và trả về tập tin được yêu cầu trong phản ứng:

public class GetFileFromZIPServlet extends HttpServlet{ 
    @Override 
    public void doGet(HttpServletRequest request, HttpServletResponse response) 
    throws ServletException, IOException{ 
    String pathToFile = request.getParameter("pathToFile"); 

    byte fileBytes[]; 
    //get the bytes of the file from the ZIP 

    //set the appropriate content type, maybe based on the file extension 
    response.setContentType("..."); 

    //write file to the response 
    response.getOutputStream().write(fileBytes); 
    } 
} 
+0

Thật không may, tôi không phải là một trong những lưu trữ các tập tin ... nhưng nó là một điểm tốt. – Oak

5

Trái ngược với những câu trả lời khác ở đây, tôi muốn muốn chỉ ra rằng các mục ZIP được nén riêng lẻ, vì vậy (theo lý thuyết) bạn không cần tải xuống bất kỳ thứ gì nhiều hơn thư mục và chính mục nhập đó. Máy chủ sẽ cần hỗ trợ tiêu đề HTTP Range để tính năng này hoạt động.

API Java chuẩn chỉ hỗ trợ đọc tệp ZIP từ tệp cục bộ và luồng đầu vào. Theo như tôi biết không có điều khoản để đọc từ các tệp từ xa truy cập ngẫu nhiên.

Vì bạn đang sử dụng TrueZip, tôi khuyên bạn nên triển khai de.schlichtherle.io.rof.ReadOnlyFile bằng cách sử dụng Apache HTTP Client và tạo một de.schlichtherle.util.zip.ZipFile với điều đó.

Điều này sẽ không cung cấp bất kỳ lợi thế nào cho lưu trữ TAR nén kể từ khi toàn bộ lưu trữ được nén lại với nhau (ngoài việc chỉ sử dụng InputStream và tiêu diệt nó khi bạn có mục nhập).

2

Vì TrueZIP 7.2, có một API ứng dụng khách mới trong đường dẫn TrueZIP của mô-đun. Đây là một thực hiện của một NIO.2 FileSystemProvider cho JSE 7.Sử dụng API này, bạn có thể truy cập HTTP URI như sau:

Path path = new TPath(new URI("http://acme.com/download/everything.tar.gz/README.TXT")); 
try (InputStream in = Files.newInputStream(path)) { 
    // Read archive entry contents here. 
    ... 
} 
Các vấn đề liên quan