设置Accept头后HttpGet返回406错误的技术求助
&filename=xxx的URL返回406 Not Acceptable的问题 我之前也踩过406错误的坑,大概率是你的请求头没有完全匹配服务器的预期——毕竟浏览器能成功,说明服务器认浏览器的请求格式,咱们把Java请求往浏览器的行为上靠就行,一步步来调整:
1. 先去掉多余的Content-Type头
你在HttpGet请求里加了Content-Type: application/zip,这其实是错误的操作:GET请求通常没有请求体,Content-Type是用来描述请求体格式的,浏览器发送GET请求时根本不会带这个头,服务器看到这个多余的头反而可能判定请求不合法,直接返回406。
删掉这行代码:
request.addHeader(HttpHeaders.CONTENT_TYPE, "application/zip");
2. 模拟浏览器的Accept头
服务器返回406的核心原因是:它认为你的Accept头和它能提供的内容不匹配。你之前只用了application/octet-stream,但浏览器发送的Accept头是更宽泛的,比如Chrome的Accept是:text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
把你的Accept头改成和浏览器一致的,至少要包含*/*(接受所有类型),比如:
request.addHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
3. 必须加上User-Agent头
这是很多人忽略的关键点!大部分服务器会校验User-Agent来区分浏览器和程序请求,没有这个头,服务器直接判定你不是合法的浏览器请求,返回406或其他错误。
复制浏览器的User-Agent(比如Chrome的)加到请求里:
request.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36");
4. 确保HttpClient自动跟随重定向
浏览器会自动处理3xx重定向,但Apache HttpClient默认的重定向策略比较严格,比如可能不允许跨协议重定向。咱们改成更宽松的策略,接近浏览器的行为:
CloseableHttpClient client = HttpClientBuilder.create() .setRedirectStrategy(new LaxRedirectStrategy()) // 允许所有合法重定向 .build();
5. 检查是否需要额外的会话头
如果浏览器访问该URL需要登录(比如有Cookie),那Java代码里也必须带上对应的Cookie头。你可以用浏览器F12的「网络」面板,查看浏览器发送的所有请求头,把必要的头(比如Cookie、Referer)都加到Java请求里。
完整示例代码
import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.client.LaxRedirectStrategy; import org.apache.http.util.EntityUtils; import java.io.FileOutputStream; import java.io.IOException; public class ZipDownloader { public static void main(String[] args) throws IOException { String targetUrl = "你的带&filename=xxx的完整URL"; // 构建支持宽松重定向的HttpClient CloseableHttpClient httpClient = HttpClientBuilder.create() .setRedirectStrategy(new LaxRedirectStrategy()) .build(); HttpGet request = new HttpGet(targetUrl); // 完全模拟浏览器的请求头 request.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36"); request.addHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8"); // 如果需要Cookie,从浏览器复制后添加 // request.addHeader("Cookie", "你的Cookie内容"); try (CloseableHttpResponse response = httpClient.execute(request)) { int statusCode = response.getStatusLine().getStatusCode(); if (statusCode == 200) { // 将响应内容写入本地文件 byte[] zipContent = EntityUtils.toByteArray(response.getEntity()); try (FileOutputStream fos = new FileOutputStream("downloaded.zip")) { fos.write(zipContent); } System.out.println("Zip文件下载成功!"); } else { System.out.println("请求失败,状态码:" + statusCode); System.out.println("响应详情:" + EntityUtils.toString(response.getEntity())); } } finally { httpClient.close(); } } }
按照上面的步骤调整后,应该就能绕过406错误,成功下载到zip文件了。
内容的提问来源于stack exchange,提问作者aarav

