Чтение первой части файла с использованием HTTP

Я хотел бы определить тип файла (обычно UTF-8), прочитав первую часть файла и проанализировав содержимое. (Тип специфичен для моего сообщества, но не находится под моим контролем и не охватывается MIME/MediaType, который обычно имеет значение TEXT_PLAIN). Я использую библиотеку org.restlet на клиенте для анализа заголовка с помощью

Request request = new Request(Method.HEAD, url);

так что я знаю длину контента и могу (если это необходимо и возможно) оценить, сколько байтов я должен загрузить для анализа

ПОЯСНЕНИЕ: я не могу использовать MediaType. Из ответа 1 кажется, что я должен ПОЛУЧИТЬ контент. Таким образом, пересмотренный вопрос будет следующим:

"Могу ли я ПОЛУЧИТЬ часть файла с помощью Restlet?"

ОТВЕТ: Следующий код делает то, что я хочу. Я поблагодарил @BalusC за указание пути. Пожалуйста, прокомментируйте, если я что-то пропустил:

public String readFirstChunk(String urlString, int byteCount) {
    String text = null;
    if (urlString != null) {
        org.restlet.Client restletClient = new org.restlet.Client(Protocol.HTTP);
        Request request = new Request(Method.GET, urlString);
        List<Range> ranges = Collections.singletonList(new Range(0, byteCount));
        request.setRanges(ranges);
        Response response = restletClient.handle(request);
        if (Status.SUCCESS_OK.equals(response.getStatus())) {
            text = processSuccessfulChunkRequest(response);
        } else if (Status.SUCCESS_PARTIAL_CONTENT .equals(response.getStatus())) {
            text = processSuccessfulChunkRequest(response);
        } else {
            System.err.println("FAILED "+response.getStatus());
        }
    }
    return text;
}

private String processSuccessfulChunkRequest(Response response) {
    String text = null;
    try {
        text = response.getEntity().getText();
    } catch (IOException e) {
        throw new RuntimeException("Cannot download chunk", e);
    }
    return text;
}

person peter.murray.rust    schedule 23.10.2010    source источник
comment
Мы обнаружили, что вы не можете улучшать файлы, которые вы читаете, чтобы они включали тип файла. Мы знаем, что можем прочитать небольшое количество байтов из каждого файла, используя InputStream. Каков твой вопрос?   -  person Tony Ennis    schedule 23.10.2010
comment
@ Тони Эннис. Я думаю, вы ответили на мой вопрос. Что я должен создать inputStream из URL-адреса и прочитать несколько байтов. Я забыл о InputStream   -  person peter.murray.rust    schedule 23.10.2010


Ответы (3)


Это возможно только в том случае, если сервер отправил Accept-Ranges и Заголовки Content-Range вместе с ETag или Last-Modified. Например.

Accept-Ranges: bytes
Content-Range: bytes 0-1233/1234
ETag: file.ext_1234_1234567890

Accept-Ranges: bytes указывает, что сервер поддерживает запросы, возвращающие частичное содержимое в указанном диапазоне байтов. Заголовок Content-Range сообщает о длине. ETag и Last-Modified указывают уникальный идентификатор файла или отметку времени последнего изменения ресурса за URI запроса.

Если эти заголовки присутствуют в ответе, вы можете запросить часть ресурса, используя If-Range и Range заголовки запроса с уникальным идентификатором файла или отметкой времени последнего изменения и желаемым диапазоном байтов.

If-Range: file.ext_1234_1234567890
Range: bytes=0-99

Приведенный выше пример возвращает первые 100 байт файла.

person BalusC    schedule 23.10.2010
comment
Спасибо. Это похоже на то, что мне нужно. Почему байты = 0-99 возвращают 100 КБ - это всегда считается в КБ? Означает ли это, что наименьший фрагмент равен 1 КБ? - person peter.murray.rust; 23.10.2010
comment
Извините, опечатка :) Должно быть B. - person BalusC; 23.10.2010

операция HEAD, как определено стандартом HTTP, не возвращает никакого содержимого, кроме информации заголовка. Поэтому, если вы отправляете запрос заголовка, вы можете проверить MIME-тип файла только из заголовка ответа HTTP.

Информацию о заголовке можно получить, просматривая представление, возвращенное из упаковки в ClientResource, и выполняя запрос заголовка. Это дает вам интерфейс высокого уровня для транспорта HTTP, и вам не нужно выполнять пользовательский анализ заголовка.

ClientResource resource = new ClientResource(url);
Representation representation = resource.head();
representation.getMediaType(); // returns the Media Type

Если вы хотите сделать предположение о типе содержимого для фактического содержимого файла, вам необходимо загрузить фактическое содержимое, например, с помощью запроса GET для этого ресурса.

Или в истинном стиле REST вы можете смоделировать дополнительный параметр запроса для своего ресурса, который вернет вашу пользовательскую метаинформацию для этого файла, например.

http://server/file?contentType

Аналогичным образом, чтобы получить фактический контент, вы можете получить дескриптор потока, а затем сделать предположение о кодировке.

Representation representation = resource.get();
InputStream stream = representation.getStream();

Чтобы указать диапазоны, если они поддерживаются сервером, вы можете установить диапазоны перед отправкой запроса на получение.

List<Range> ranges = new ArrayList<Range>();
ranges.add(new Range(0,100)); // this would request the first 100 bytes
resource.setRanges(ranges);
Representation representation = resource.get();

Перед возвратом убедитесь, что вы полностью используете ответ (поток).

Я предлагаю вам изучить другие способы, которые помогут вам определить тип контента. Например, здесь кодировка Java и Windows или http://glaforge.free.fr/wiki/index.php?wiki=GuessEncoding

person Joey    schedule 23.10.2010
comment
Я недостаточно ясно выразился - мне нужен контент, а не медиа-тип - person peter.murray.rust; 23.10.2010
comment
В JavaScript вы читаете часть файла и отправляете запрос Ajax, который получает тип содержимого. - person Dead Programmer; 23.10.2010

Поскольку это ваш контент, почему бы просто не включить все необходимые данные в первые несколько байтов каждого файла?

person Tony Ennis    schedule 23.10.2010
comment
извините - я не могу этого сделать. Это не все сгенерировано моим приложением - person peter.murray.rust; 23.10.2010
comment
Поскольку мы не знаем содержимого/макета файла, я не знаю, что еще предложить. Существуют методы для чтения небольшого количества байтов из файлового потока. - person Tony Ennis; 23.10.2010
comment
Похоже, эти методы именно то, что я хотел бы! - person peter.murray.rust; 23.10.2010