Я пытаюсь получить кучу pdf-ссылок из веб-службы, и я хочу дать пользователю размер файла каждой ссылки.
Есть ли способ выполнить эту задачу?
благодаря
Я пытаюсь получить кучу pdf-ссылок из веб-службы, и я хочу дать пользователю размер файла каждой ссылки.
Есть ли способ выполнить эту задачу?
благодаря
Используя запрос 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();
}
}
}
Попробуйте использовать метод HTTP HEAD. Он возвращает только заголовки HTTP. Заголовок Content-Length
должен содержать необходимую информацию.
Принятый ответ склонен к 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();
}
}
}
Обновление: принятый ответ исправлен.
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...
...
}
}
Вы уже пытались использовать getContentLength для соединения с URL? Если сервер отвечает за допустимый заголовок, вы должны получить размер документа.
Но имейте в виду, что веб-сервер может также вернуть файл в куски. В этом случае IIRC метод длины содержимого вернет либо размер одного фрагмента (<= 1.4), либо -1 (> 1.4).
Вы можете попробовать это.
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;
}
Если вы находитесь на 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
}
}
Я перепробовал все возможные способы, но он всегда возвращается -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]}