Самый быстрый способ получить тип контента

#java #url #content-type

#java #url #тип содержимого

Вопрос:

Мне нужно проверить тип контента (если это изображение, аудио или видео) URL-адреса, который был вставлен пользователем. У меня есть код, подобный этому:

 URL url = new URL(urlname);
URLConnection connection = url.openConnection();
connection.connect();
String contentType = connection.getContentType();
  

Я получаю тип контента, но проблема в том, что, похоже, необходимо загрузить весь файл, чтобы проверить его тип контента. Так что это длится слишком много времени, когда файл довольно большой. Мне нужно использовать его в приложении Google App Engine, чтобы запросы были ограничены 30 секундами.

Есть ли какой-либо другой способ получить тип содержимого URL-адреса без загрузки файла (чтобы это можно было сделать быстрее)?

Комментарии:

1. Просто идея: как насчет захвата первых n байтов и последующего закрытия соединения? В большинстве случаев должно быть возможно угадать тип содержимого только по началу файла. Но я здесь не профессионал.

2. @pintxo зачем вам это делать, если вы можете прочитать параметр заголовка: Content-Type и вместо получения всего запроса с помощью GET вы просто выполняете HEAD вместо этого

Ответ №1:

Благодаря ответу DaveHowes и поискам в Google о том, как получить HEAD, я получил это таким образом:

 URL url = new URL(urlname);
HttpURLConnection connection = (HttpURLConnection)  url.openConnection();
connection.setRequestMethod("HEAD");
connection.connect();
String contentType = connection.getContentType();
  

Ответ №2:

Если «другой» конец поддерживает это, не могли бы вы использовать HEAD метод HTTP?

Комментарии:

1. Помните о перенаправлениях, я столкнулся с такой же проблемой при удаленной проверке содержимого. Смотрите мой код ниже, где я проверял.

Ответ №3:

Помните о перенаправлениях, я столкнулся с такой же проблемой при удаленной проверке содержимого.
Вот мое исправление:

 /**
 * Http HEAD Method to get URL content type
 *
 * @param urlString
 * @return content type
 * @throws IOException
 */
public static String getContentType(String urlString) throws IOException{
    URL url = new URL(urlString);
    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
    connection.setRequestMethod("HEAD");
    if (isRedirect(connection.getResponseCode())) {
        String newUrl = connection.getHeaderField("Location"); // get redirect url from "location" header field
        logger.warn("Original request URL: '{}' redirected to: '{}'", urlString, newUrl);
        return getContentType(newUrl);
    }
    String contentType = connection.getContentType();
    return contentType;
}

/**
 * Check status code for redirects
 * 
 * @param statusCode
 * @return true if matched redirect group
 */
protected static boolean isRedirect(int statusCode) {
    if (statusCode != HttpURLConnection.HTTP_OK) {
        if (statusCode == HttpURLConnection.HTTP_MOVED_TEMP
            || statusCode == HttpURLConnection.HTTP_MOVED_PERM
                || statusCode == HttpURLConnection.HTTP_SEE_OTHER) {
            return true;
        }
    }
    return false;
}
  

Вы также могли бы поставить некоторый счетчик для maxRedirectCount , чтобы избежать бесконечного цикла перенаправления, но это здесь не рассматривается. Это просто вдохновение.

Комментарии:

1. неплохо. зачем вам нужно спрашивать: if (StatusCode != HttpURLConnection. HTTP_OK) {

2. @Dejell это для перенаправления дескриптора

3. Вы можете использовать java.net.HttpURLConnection.setFollowRedirects(boolean) для того, чтобы уменьшить размер вашего шаблонного кода.

4. setFollowRedirects кажется, true по умолчанию docs.oracle.com/javase/7/docs/api/java/net / …

Ответ №4:

Я столкнулся с аналогичной задачей, когда мне нужно было проверить тип содержимого URL-адреса, и способ, которым я справился с этим, — с помощью retrofit. Сначала вы должны определить конечную точку для ее вызова с URL-адресом, который вы хотите проверить:

 @GET
suspend fun getContentType(@Url url: String): Response<Unit>
  

Затем вы вызываете это следующим образом, чтобы получить заголовок типа контента:

 api.getContentType(url).headers()["content-type"]