FileUtils.copyURLToFile(URL, File)方法中如何指定User Agent和Referer?

How to specify User Agent and Referer in FileUtils.copyURLToFile(URL, File) method?

我正在使用 FileUtils.copyURLToFile(URL, File), an Apache Commons IO 2.4 部分,将文件下载并保存在我的计算机上。问题是某些站点在没有引荐来源网址和用户代理数据的情况下拒绝连接。

我的问题:

  1. 有什么方法可以指定用户代理和引荐来源网址到 copyURLToFile 方法吗?
  2. 或者我应该使用另一种方法来下载文件,然后将给定的 InputStream 保存到文件中吗?

可能不会,除非你能掌握打开 URL 的底层机制。

我推荐使用 https://hc.apache.org/ 库。这有很多关于 headers 等的功能

我用 HttpComponents 而不是 Commons-IO 重新实现了功能。此代码允许您根据 URL 下载 Java 中的文件并将其保存在特定目的地。

最终代码:

public static boolean saveFile(URL imgURL, String imgSavePath) {

    boolean isSucceed = true;

    CloseableHttpClient httpClient = HttpClients.createDefault();

    HttpGet httpGet = new HttpGet(imgURL.toString());
    httpGet.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.11 Safari/537.36");
    httpGet.addHeader("Referer", "https://www.google.com");

    try {
        CloseableHttpResponse httpResponse = httpClient.execute(httpGet);
        HttpEntity imageEntity = httpResponse.getEntity();

        if (imageEntity != null) {
            FileUtils.copyInputStreamToFile(imageEntity.getContent(), new File(imgSavePath));
        }

    } catch (IOException e) {
        isSucceed = false;
    }

    httpGet.releaseConnection();

    return isSucceed;
}

当然,上面的代码需要更多 space 然后只是一行代码:

FileUtils.copyURLToFile(imgURL, new File(imgSavePath),
                        URLS_FETCH_TIMEOUT, URLS_FETCH_TIMEOUT);

但它会让您更好地控制进程,让您不仅可以指定超时,还可以指定 User-AgentReferer 值,这对许多网站来说都是至关重要的。

完成关于如何处理超时的已接受答案:

如果你想设置超时,你必须像这样创建 CloseableHttpClient

RequestConfig config = RequestConfig.custom()
                 .setConnectTimeout(connectionTimeout)
                 .setConnectionRequestTimeout(readDataTimeout)
                 .setSocketTimeout(readDataTimeout)
                 .build();

CloseableHttpClient httpClient = HttpClientBuilder
                 .create()
                 .setDefaultRequestConfig(config)
                 .build();

并且,使用 try-with-resource 语句来创建您的 CloseableHttpClient 可能是个好主意来处理其关闭:

try (CloseableHttpClient httpClient = HttpClientBuilder.create().setDefaultRequestConfig(config).build()) {
  ... rest of the code using httpClient
}