Скачать файл с Apache HttpClient

То, что я пытаюсь сделать, это загрузить файл с httpclient. На данный момент мой код следующий.

    HttpClient client = HttpClientBuilder.create().build();
    HttpGet request = new HttpGet(downloadURL);     


    HttpResponse response = client.execute(request);

    HttpEntity entity = response.getEntity();
    if (entity != null) {
        FileOutputStream fos = new FileOutputStream("C:\\file");
        entity.writeTo(fos);
        fos.close();
    }

Мой URL для загрузки выглядит примерно так: http://example.com/file/afz938f348dfa3

Как видите, расширение файла отсутствует (по крайней мере, в URL), однако, когда я захожу на URL с помощью обычного браузера, он загружает файл "asdasdaasda.txt" или "asdasdasdsd.pdf" (имя отличается от URL, и расширение не всегда одно и то же, зависит от того, что я пытаюсь загрузить).

Мой http ответ выглядит так:

Дата: понедельник, 29 мая 2017 г. 14:57:14 GMT Сервер: Apache/2.4.10 Content-Disposition: attachment; filename="149606814324_testfile.txt" Accept-Ranges: байты Cache-Control: public, max-age=0 Последнее изменение: понедельник, 29 мая 2017 14:29:06 GMT Etag: W/"ead-15c549c4678-gzip" Содержимое -Тип: текст / обычный; charset=UTF-8 Зависит от: Accept-Encoding. Content-Encoding: gzip Content-Length: 2554 Keep-Alive: timeout=5, max=100 Соединение: Keep-Alive

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

3 ответа

Решение

Вы можете получить имя файла и расширение из вашего ответа content-disposition заголовок

Сначала получите заголовок, а затем проанализируйте его для имени файла, как описано здесь, то есть:

HttpEntity entity = response.getEntity();
if (entity != null) {
    String name = response.getFirstHeader('Content-Disposition').getValue();
    String fileName = disposition.replaceFirst("(?i)^.*filename=\"([^\"]+)\".*$", "$1");
    FileOutputStream fos = new FileOutputStream("C:\\" + fileName);
    entity.writeTo(fos);
    fos.close();
}

Более формальным способом было бы использовать API HeaderElements:

    Optional<String> resolveFileName(HttpResponse response) {
        return Arrays.stream(response.getFirstHeader("Content-Disposition").getElements())
                .map(element -> element.getParameterByName("filename"))
                .filter(Objects::nonNull)
                .map(NameValuePair::getValue)
                .findFirst();
    }

Код Java 11 для загрузки файла с помощью java.net.http.HttpClient

      import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;

...

      public static void downloadFile(String productId) throws IOException, InterruptedException {
        String url = "https://sameer-platform.com/v1/products/" + productId + "/download/model";

        HttpClient client = HttpClient.newHttpClient();
        HttpRequest request = HttpRequest.newBuilder().uri(URI.create(url)).build();

        // Creates new File at provided location user.dir and copies the filename from Content-Disposition
        HttpResponse<Path> response = client.send(request,
                HttpResponse.BodyHandlers.ofFileDownload(Path.of(System.getProperty("user.dir")),
                        StandardOpenOption.CREATE, StandardOpenOption.WRITE));

        System.out.println(response.statusCode());
        System.out.println(response.headers());
        Path path = response.body();
        System.out.println("Path=" + path); // Absolute Path of downloaded file
    }
Другие вопросы по тегам