使用HttpURLConnection向S3写文件需调用getResponseCode的原因咨询
关于HttpURLConnection向AWS S3写入文件的异常问题
我使用HttpURLConnection向AWS S3存储桶写入文件时发现,只有在调用getInputStream或getResponseCode后,输出流的write命令才会生效。注释掉获取responseCode的代码行后,文件就无法写入S3。我希望代码无需调用该方法也能正常工作,恳请帮忙解释此现象,是否必须读取responseCode?
原始代码
URL endpointUrl = new URL("muURL"); HttpURLConnection connection = (HttpURLConnection) endpointUrl.openConnection(); connection.setRequestMethod("PUT"); connection.setRequestProperty("Authorization", authorization); connection.setRequestProperty("x-amz-content-sha256", hashPayload); connection.setRequestProperty("X-Amz-Date", myDate); connection.setRequestProperty("Content-Type","application/octet-stream"); connection.setRequestProperty("Content-Length",contentLen); //connection.setRequestProperty("Accept","*/*"); connection.setUseCaches(false); //connection.setDoInput(true); connection.setDoOutput(true); DataOutputStream wr = new DataOutputStream(connection.getOutputStream()); wr.writeBytes(payload); StringBuilder builder = new StringBuilder(); // 如果注释掉这行获取responseCode的代码,文件就无法写入S3 builder.append(connection.getResponseCode()); wr.flush(); wr.close(); connection.disconnect();
问题原因
HttpURLConnection采用延迟发送请求的设计逻辑:当你往输出流写入数据时,数据只是暂存在本地缓冲区,并没有立即发送到S3服务器。只有当你尝试读取服务器的响应(比如调用getResponseCode()、getInputStream()这类方法),它才会将缓冲区的数据发送出去,并等待服务器确认接收。
如果跳过读取响应的步骤,请求根本没有被发送到S3,自然不会有文件写入。
不是必须读取responseCode,但必须触发请求完成
你不需要非得获取响应码,但必须触发HttpURLConnection完成请求发送的流程。可以用以下几种方式替代:
- 调用
connection.getResponseMessage()(和getResponseCode()一样会触发请求发送) - 写完数据后,先关闭输出流,再调用
connection.getInputStream()并直接关闭(即使不需要响应内容)
规范代码修正
你的代码还存在顺序问题:应该先flush并关闭输出流,再读取响应,这样更符合HttpURLConnection的工作逻辑,修正后的代码如下:
URL endpointUrl = new URL("muURL"); HttpURLConnection connection = (HttpURLConnection) endpointUrl.openConnection(); connection.setRequestMethod("PUT"); connection.setRequestProperty("Authorization", authorization); connection.setRequestProperty("x-amz-content-sha256", hashPayload); connection.setRequestProperty("X-Amz-Date", myDate); connection.setRequestProperty("Content-Type","application/octet-stream"); connection.setRequestProperty("Content-Length",contentLen); connection.setUseCaches(false); connection.setDoOutput(true); DataOutputStream wr = new DataOutputStream(connection.getOutputStream()); wr.writeBytes(payload); // 先推送缓冲区数据并关闭输出流 wr.flush(); wr.close(); // 触发请求发送,即使不需要响应码,也需调用此方法确保请求完成 connection.getResponseCode(); connection.disconnect();
总结
不是必须读取响应码,但必须触发HttpURLConnection的请求发送流程——因为它不会自动发送请求,必须等到你尝试读取响应时才会执行真正的网络交互。如果跳过这一步,本地缓冲区的数据永远不会发往S3,自然无法完成文件写入。
内容的提问来源于stack exchange,提问作者Uma
相关产品推荐
相关产品推荐

