Java如何从使用doPost请求的网站下载需提交参数的文件?
问题解决思路
你当前使用的FileUtils.copyURLToFile默认发送GET请求,而目标接口仅接收POST请求携带参数,返回的实际是错误响应页而非RAR压缩包,所以下载到的文件显示损坏,可按以下步骤实现正确下载:
第一步:抓取请求必填参数和头信息
- 打开浏览器按下F12调出开发者工具,切换到「网络」面板
- 在目标网站手动选择你要下载的参数,点击下载按钮
- 在网络请求列表中找到路径为
MobiliterServlet的POST请求,记录两个部分内容:- 「载荷」页签下的所有表单键值对(就是你在网站选择的参数对应的提交值)
- 「请求头」页签下的
Content-Type、User-Agent、Referer三个字段值,部分站点会校验这些头避免爬虫访问
第二步:编写POST请求下载代码
下面的实现兼容你已经引入的Apache Commons IO依赖,无需额外引入第三方包:
import org.apache.commons.io.FileUtils; import java.io.*; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; public class PostDownloader { public static void main(String[] args) { String postUrl = "https://servizissiir.regione.emilia-romagna.it/FlussiMTS/MobiliterServlet"; String localRarPath = "src/download.rar"; // 替换为你实际抓包拿到的所有表单参数 Map<String, String> params = new HashMap<>(); params.put("参数1的键", "参数1的值"); params.put("参数2的键", "参数2的值"); // 有多少个参数就追加多少条 try { URL url = new URL(postUrl); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); // 设置请求方法为POST conn.setRequestMethod("POST"); // 替换为你实际抓包拿到的请求头 conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); conn.setRequestProperty("User-Agent", "你抓包拿到的User-Agent值"); conn.setRequestProperty("Referer", "https://servizissiir.regione.emilia-romagna.it/FlussiMTS/"); // 允许向请求体写参数 conn.setDoOutput(true); conn.setConnectTimeout(20000); conn.setReadTimeout(20000); // 拼接表单参数到请求体 StringBuilder paramStr = new StringBuilder(); for (Map.Entry<String, String> entry : params.entrySet()) { if (paramStr.length() > 0) { paramStr.append("&"); } paramStr.append(URLEncoder.encode(entry.getKey(), StandardCharsets.UTF_8.name())) .append("=") .append(URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8.name())); } // 输出参数到请求 try (OutputStream os = conn.getOutputStream()) { os.write(paramStr.toString().getBytes(StandardCharsets.UTF_8)); os.flush(); } // 直接读取响应字节流写入本地文件,不要做转码 try (InputStream is = conn.getInputStream()) { FileUtils.copyInputStreamToFile(is, new File(localRarPath)); } conn.disconnect(); System.out.println("下载完成"); } catch (IOException e) { e.printStackTrace(); } } }
常见注意事项
- 如果站点有会话校验,你需要先GET请求网站首页,获取响应头里的
Set-Cookie值,再把Cookie值加到POST请求头里即可 - 如果你抓包看到参数是JSON格式而非表单格式,把Content-Type改成
application/json,请求体直接写JSON字符串即可 - 不要对响应流做字符串转码操作,直接读取字节写入文件,否则会导致压缩包损坏
内容的提问来源于stack exchange,提问作者Vincenzo Pirrera
相关产品推荐
相关产品推荐

