Как вычислить размер файла из URL-адреса в java

Я пытаюсь получить кучу pdf-ссылок из веб-службы, и я хочу дать пользователю размер файла каждой ссылки.

Есть ли способ выполнить эту задачу?

благодаря

Ответ 1

Используя запрос HEAD, вы можете сделать что-то вроде этого:

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

Ответ 2

Попробуйте использовать метод HTTP HEAD. Он возвращает только заголовки HTTP. Заголовок Content-Length должен содержать необходимую информацию.

Ответ 3

Принятый ответ склонен к NullPointerException, не работает для файлов> 2GiB и содержит ненужный вызов getInputStream(). Здесь фиксированный код:

public long getFileSize(URL url) {
  HttpURLConnection conn = null;
  try {
    conn = (HttpURLConnection) url.openConnection();
    conn.setRequestMethod("HEAD");
    return conn.getContentLengthLong();
  } catch (IOException e) {
    throw new RuntimeException(e);
  } finally {
    if (conn != null) {
      conn.disconnect();
    }
  }
}

Обновление: принятый ответ исправлен.

Ответ 4

HTTP-ответ имеет заголовок Content-Length, поэтому вы можете запросить объект URLConnection для этого значения.

Как только соединение URL было открыто, вы можете попробовать что-то вроде этого:

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...
       ...
    }
}

Ответ 5

Вы уже пытались использовать getContentLength для соединения с URL? Если сервер отвечает за допустимый заголовок, вы должны получить размер документа.

Но имейте в виду, что веб-сервер может также вернуть файл в куски. В этом случае IIRC метод длины содержимого вернет либо размер одного фрагмента (<= 1.4), либо -1 (> 1.4).

Ответ 6

Вы можете попробовать это.

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;
    }

Ответ 7

Если вы находитесь на Android, вот решение на Java:

/**@return the file size of the given file url , or -1L if there was any kind of error while doing so*/
@WorkerThread
public static long getUrlFileLength(String url) {
    try {
        final HttpURLConnection urlConnection = (HttpURLConnection) new URL(url).openConnection();
        urlConnection.setRequestMethod("HEAD");
        final String lengthHeaderField = urlConnection.getHeaderField("content-length");
        Long result = lengthHeaderField == null ? null : Long.parseLong(lengthHeaderField);
        return result == null || result < 0L ? -1L : result;
    } catch (Exception ignored) {
    }
    return -1L;
}

А в Котлине

/**@return the file size of the given file url , or -1L if there was any kind of error while doing so*/
@WorkerThread
fun getUrlFileLength(url: String): Long {
    return try {
        val urlConnection = URL(url).openConnection() as HttpURLConnection
        urlConnection.requestMethod = "HEAD"
        urlConnection.getHeaderField("content-length")?.toLongOrNull()?.coerceAtLeast(-1L)
                ?: -1L
    } catch (ignored: Exception) {
        -1L
    }
}

Если ваше приложение от Android N, вы можете использовать это вместо:

/**@return the file size of the given file url , or -1L if there was any kind of error while doing so*/
@WorkerThread
fun getUrlFileLength(url: String): Long {
    return try {
        val urlConnection = URL(url).openConnection() as HttpURLConnection
        urlConnection.requestMethod = "HEAD"
        urlConnection.contentLengthLong.coerceAtLeast(-1L)
    } catch (ignored: Exception) {
        -1L
    }
}

Ответ 8

Я перепробовал все возможные способы, но он всегда возвращается -1

Также ниже прилагаются данные заголовка

{null=[HTTP/1.1 200 OK], Accept-Ranges=[bytes], Cache-Control=[max-age=2592000], Connection=[keep-alive, Keep-Alive], Content-Type=[application/vnd.android.package-archive], Date=[Thu, 25 Jul 2019 14:01:44 GMT], ETag=["3f416f-58e6adf532900-gzip"], Expires=[Sat, 24 Aug 2019 14:01:44 GMT], Keep-Alive=[timeout=3, max=75], Last-Modified=[Wed, 24 Jul 2019 10:35:48 GMT], Server=[Apache/2.4.39 (cPanel) OpenSSL/1.0.2r mod_bwlimited/1.4 Phusion_Passenger/5.3.7], Transfer-Encoding=[chunked], Upgrade=[h2,h2c], Vary=[Accept-Encoding,User-Agent], X-Android-Received-Millis=[1564063303579], X-Android-Response-Source=[NETWORK 200], X-Android-Selected-Protocol=[http/1.1], X-Android-Sent-Millis=[1564063302765]}