2012-10-09 39 views
12

Tôi đang cố gắng nhận một loạt các liên kết pdf từ một dịch vụ web và tôi muốn cung cấp cho người dùng kích thước tệp của mỗi liên kết.Cách tính kích thước tệp từ URL trong java

Có cách nào để thực hiện tác vụ này không?

Cảm ơn

+0

Tôi sợ bạn sẽ phải tải xuống tệp ít nhất một lần để có kích thước chính xác. (bạn có thể muốn lưu trữ trong tương lai, nhưng nếu các tệp thay đổi trên máy chủ, dữ liệu sẽ cũ) – Nishant

+1

@Nishant Điều đó không đúng. Yêu cầu 'HTTP HEAD' trả về thông tin về những gì bạn sẽ nhận được nếu bạn đã thực hiện yêu cầu' HTTP GET', bao gồm kích thước của yêu cầu được trả về. Bạn chắc chắn có thể thực hiện yêu cầu 'HEAD' và phân tích cú pháp phản hồi. – Thor84no

+1

ah, ok. Rất vui được biết. Cảm ơn @ Thor84no – Nishant

Trả lời

22

Sử dụng một yêu cầu HEAD, bạn có thể làm một cái gì đó như thế này:

private static int getFileSize(URL url) { 
    URLConnection conn = null; 
    try { 
     conn = url.openConnection(); 
     if(conn instanceof HttpURLConnection) { 
      ((HttpURLConnection)conn).setRequestMethod("HEAD"); 
     } 
     conn.getInputStream(); 
     return conn.getContentLength(); 
    } catch (IOException e) { 
     throw new RuntimeException(e); 
    } finally { 
     if(conn instanceof HttpURLConnection) { 
      ((HttpURLConnection)conn).disconnect(); 
     } 
    } 
} 
+0

Tôi nhận ngoại lệ bên dưới: java.io.IOException: Máy chủ trả về mã phản hồi HTTP: 405 cho URL. Tôi muốn mở liên kết pdf trong trình duyệt. Có nghĩa là url này sẽ không cho phép yêu cầu head? – javaMan

+1

Bạn có thể chia sẻ URL yêu cầu của mình không? –

+0

Tôi xin lỗi ... Url cần thông tin đăng nhập của tôi. Tôi không thể chia sẻ nó. :( – javaMan

6

Cố gắng sử dụng phương thức HEAD HTTP. Nó chỉ trả về các tiêu đề HTTP. Tiêu đề Content-Length phải chứa thông tin bạn cần.

2

Bạn đã thử sử dụng getContentLength trên kết nối URL chưa? Trong trường hợp máy chủ phản hồi một tiêu đề hợp lệ, bạn sẽ nhận được kích thước của tài liệu.

Nhưng lưu ý rằng máy chủ web cũng có thể trả về tệp theo khối. Trong trường hợp này IIRC phương thức chiều dài nội dung sẽ trả về kích thước của một đoạn (< = 1.4) hoặc -1 (> 1.4).

3

Câu trả lời HTTP có một tiêu đề Content-Length, vì vậy bạn có thể truy vấn các đối tượng URLConnection cho giá trị này.

Khi kết nối URL đã được mở ra, bạn có thể thử một cái gì đó như thế này:

List values = urlConnection.getHeaderFields().get("content-Length") 
if (values != null && !values.isEmpty()) { 

    // getHeaderFields() returns a Map with key=(String) header 
    // name, value = List of String values for that header field. 
    // just use the first value here. 
    String sLength = (String) values.get(0); 

    if (sLength != null) { 
     //parse the length into an integer... 
     ... 
    } 
} 
0

Bạn có thể thử này ..

private long getContentLength(HttpURLConnection conn) { 
    String transferEncoding = conn.getHeaderField("Transfer-Encoding"); 
    if (transferEncoding == null || transferEncoding.equalsIgnoreCase("chunked")) { 
     return conn.getHeaderFieldInt("Content-Length", -1); 
    } else { 
     return -1; 
    } 
3

Câu trả lời được chấp nhận là dễ bị NullPointerException, không làm việc cho tệp> 2GiB và chứa cuộc gọi không cần thiết đến getInputStream(). Đây là mã cố định:

public long getFileSize(URL url) { 
    HttpURLConnection conn = null; 
    try { 
    conn = (HttpURLConnection) url.openConnection(); 
    conn.setRequestMethod("HEAD"); 
    return conn.getContentLengthLong(); 
    } catch (IOException e) { 
    return -1; 
    // Or wrap into a (custom, if desired) RuntimeException so exceptions are propagated. 
    // throw new RuntimeException(e); 
    // Alternatively you can just propagate IOException, but, urgh. 
    } finally { 
    if (conn != null) { 
     conn.disconnect(); 
    } 
    } 
} 
Các vấn đề liên quan