使用Apache HttpClient下载文件

3

我的目标是使用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();
    }
我的下载链接看起来像这样:http://example.com/file/afz938f348dfa3。正如你所看到的,在URL中没有文件扩展名,但是当我使用普通浏览器访问该URL时,它会下载文件“asdasdaasda.txt”或“asdasdasdsd.pdf”(名称与URL不同,扩展名不总是相同的,这取决于我要下载什么)。我的HTTP响应如下所示: 日期:Mon, 29 May 2017 14:57:14 GMT 服务器:Apache/2.4.10 内容-Disposition:attachment; filename="149606814324_testfile.txt" 接受范围:字节 缓存控制:public,max-age=0 最后修改时间:星期一,2017年5月29日14:29:06 GMT ETag:W/"ead-15c549c4678-gzip" 内容类型:text/plain; charset=UTF-8 变化:接受编码方式 内容编码:gzip 内容长度:2554 保持活动状态:超时=5,最大=100 连接:保持活动状态 如何使我的Java代码能够自动下载带有正确名称和扩展名的文件到指定文件夹?

2
你可能需要使用这个头部,但这取决于文件从服务器上是如何提供的;请展示请求URL时收到的纯HTTP响应样例,或者提供一个有效可访问的URL以便获取更多帮助。 - Ovidiu Dolha
日期:2017年5月29日星期一14:57:14 GMT服务器:Apache/2.4.10内容-Disposition:附件; 文件名="149606814324_testfile.txt"接受范围:字节缓存控制:公共,最大年龄=0上次修改时间:2017年5月29日星期一14:29:06 GMTEtag:W/"ead-15c549c4678-gzip"内容类型:纯文本; 字符集=UTF-8变化:接受编码内容编码:gzip内容长度:2554保持活动状态:超时=5,最大=100连接:保持活动 - retArdos
3个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
5
更正式的方法是使用HeaderElements API:
    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();
    }

5
你可以从响应的 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();
}

1
非常感谢,您的代码似乎运行良好。然而,我之前编写了一个版本,其中包括以下这行代码:String fileName = disposition.substring(disposition.indexOf(""") + 1, disposition.lastIndexOf(""")); 而不是 String fileName = disposition.replaceFirst("(?i)^.filename="([^"]+)".$", "$1"); 请问这两者有什么区别呢?它们看起来都能得到相同的结果。 - retArdos
@retArdos,你的方法更简单。 - Manu Manjunath

1

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
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,