Java从URL获取图片大小:本地正常AWS Ubuntu服务器返回-1问题排查
我来帮你梳理这个问题,本地正常但服务器返回-1的情况,大多和环境差异或者Java URLConnection的特性有关,咱们一步步排查:
1. 先替换过时的getContentLength()方法
getContentLength()是个老旧的方法,它只支持int范围的大小,而且当服务器用分块传输编码(Transfer-Encoding: chunked)返回内容时,会直接返回-1。建议换成getContentLengthLong(),它支持更大的数值范围,兼容性更好:
URL url = new URL("https://www.bithumb.com/resources/img/comm/sp_coin.png?v=180510"); long image_size = url.openConnection().getContentLengthLong(); System.out.println("Image size:: " + image_size);
2. 检查AWS服务器的网络连通性与响应头
先在AWS服务器上用curl命令直接测试目标URL,看看服务器返回的响应里有没有Content-Length字段:
curl -I https://www.bithumb.com/resources/img/comm/sp_coin.png?v=180510
- 如果输出里没有
Content-Length,说明目标服务器本身就没返回这个字段,Java自然拿不到,这时候你需要通过读取流的方式来计算大小(比如把流读到ByteArrayOutputStream里,再取大小)。 - 如果有
Content-Length,那问题就出在Java的请求处理上,继续往下排查。
3. 模拟浏览器请求头,避免被网站拦截
有些网站会拒绝非浏览器的请求,服务器上的Java请求默认没有携带User-Agent等头信息,导致服务器返回异常响应。你可以给URLConnection添加浏览器风格的请求头:
URL url = new URL("https://www.bithumb.com/resources/img/comm/sp_coin.png?v=180510"); URLConnection conn = url.openConnection(); // 添加User-Agent模拟浏览器 conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"); // 可以再加个Accept头 conn.setRequestProperty("Accept", "image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8"); long image_size = conn.getContentLengthLong(); System.out.println("Image size:: " + image_size);
4. 排查SSL证书信任问题
本地Java环境可能已经信任了目标网站的SSL证书,但AWS服务器上的Java证书库(cacerts)可能没有包含该证书,导致请求失败(虽然这种情况通常会抛出SSL异常,但也有可能静默返回-1)。你可以临时禁用证书验证来测试(仅限测试,生产环境不要这么做):
// 临时禁用SSL证书验证,仅用于测试 TrustManager[] trustAllCerts = new TrustManager[]{ new X509TrustManager() { public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) {} public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) {} } }; SSLContext sc = SSLContext.getInstance("SSL"); sc.init(null, trustAllCerts, new java.security.SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); // 禁用主机名验证 HostnameVerifier allHostsValid = (hostname, session) -> true; HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid); // 之后再执行原请求 URL url = new URL("https://www.bithumb.com/resources/img/comm/sp_coin.png?v=180510"); long image_size = url.openConnection().getContentLengthLong(); System.out.println("Image size:: " + image_size);
如果这样能拿到正确大小,就需要把目标网站的证书导入到AWS服务器的Java cacerts文件中。
5. 检查AWS服务器的代理/VPC限制
AWS服务器可能处于VPC私有子网,或者有出站代理配置,导致请求无法正常到达目标网站。你可以先测试服务器能不能ping通目标域名:
ping www.bithumb.com
如果ping不通,说明网络有问题,需要检查VPC的出站规则、安全组配置,或者代理设置。如果ping通但curl拿不到响应,可能是端口被封禁(比如443端口),需要检查安全组是否允许出站HTTPS流量。
内容的提问来源于stack exchange,提问作者jini

