【问题标题】:How to calculate a file size from URL in java如何从java中的URL计算文件大小
【发布时间】:2012-10-09 12:58:59
【问题描述】:

我正在尝试从 Web 服务获取一堆 pdf 链接,我想为用户提供每个链接的文件大小。

有没有办法完成这个任务?

谢谢

【问题讨论】:

  • 恐怕您必须至少下载一次文件才能获得准确的大小。 (您可能希望存储以备将来使用,但如果服务器上的文件发生更改,则数据将过时)
  • @Nishant 这不是真的。 HTTP HEAD 请求返回有关如果您执行 HTTP GET 请求会得到什么的信息,其中应包括返回请求的大小。您当然可以发出HEAD 请求并解析响应。
  • 啊,好的。很高兴知道。谢谢@Thor84no
  • 但content-length 是可选的,可能不存在

标签: java jakarta-ee


【解决方案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();
        }
    }
}

【讨论】:

  • 我得到以下异常:java.io.IOException:服务器返回 HTTP 响应代码:URL 为 405。我很高兴在浏览器中打开 pdf 链接。这是否意味着这个网址不允许头部请求?
  • 您能分享您的请求网址吗?
  • 对不起... Url 需要我的凭据。我不能分享它。 :(
  • @ravi 如果 405,使用“GET”而不是“HEAD”。
  • 它返回 -1。当我在调试模式下运行并查看 conn 对象时,我看到许多字段为 null 或 false 或 -1
【解决方案2】:

接受的答案很容易出现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();
    }
  }
}

更新:已接受的答案已修复。

【讨论】:

    【解决方案3】:

    尝试使用 HTTP HEAD 方法。它仅返回 HTTP 标头。标题Content-Length 应该包含您需要的信息。

    【讨论】:

      【解决方案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】:

        您是否已经尝试在 URL 连接上使用 getContentLength? 如果服务器响应一个有效的标题,你应该得到文档的大小。

        但请注意,网络服务器也可能以块的形式返回文件。在这种情况下,IIRC 内容长度方法将返回一个块的大小 (1.4)。

        【讨论】:

          【解决方案6】:

          如果您使用的是 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;
          }
          

          在 Kotlin 中:

          /**@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
              }
          }
          

          【讨论】:

          • 我已经尝试了所有可能的方法,但它总是返回-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, 2019 年 8 月 24 日 14:01:44 GMT],Keep-Alive=[timeout=3, max=75],Last-Modified=[Wed,2019 年 7 月 24 日 10:35:48 GMT],服务器=[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]}
          • @golchha21 这是什么?
          • 这是我使用urlConnection.headerFields时返回的数据
          【解决方案7】:

          你可以试试这个..

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

          【讨论】:

            猜你喜欢
            • 2010-10-12
            • 1970-01-01
            • 2011-01-12
            • 1970-01-01
            • 1970-01-01
            • 2014-07-23
            • 2012-11-13
            相关资源
            最近更新 更多