最近一個項目中用到了Spring MVC 計時器 + HttpClient 發送http請求,封裝post請求代碼如下:
httpClient = new DefaultHttpClient();
post = new HttpPost(StaticAttributes.TASK_FILE_URL);
// 請求頭信息
post.setHeader("enctype", "multipart/form-data");
post.setHeader("File-Path", DeEnCode.encode(filePath));
post.addHeader("Connection", "Keep-Alive");
// 封裝請求參數和文件
FileBody fileBody = new FileBody(file);
MultipartEntity reqEntity = new MultipartEntity();
reqEntity.addPart("file", fileBody);
// 設置請求
post.setEntity(reqEntity);
response = httpClient.execute(post);
其中請求頭 post.setHeader("File-Path", DeEnCode.encode(filePath)); value值用到了Base64加密。然後發送請求出現了一個很頭疼的錯誤
java.net.SocketException: Connection reset by peer: socket write error
at java.net.SocketOutputStream.socketWrite0(Native Method)
at java.net.SocketOutputStream.socketWrite(Unknown Source)
at java.net.SocketOutputStream.write(Unknown Source)
at org.apache.http.impl.io.AbstractSessionOutputBuffer.flushBuffer(AbstractSessionOutputBuffer.java:147)
at org.apache.http.impl.io.AbstractSessionOutputBuffer.flush(AbstractSessionOutputBuffer.java:154)
at org.apache.http.impl.io.ContentLengthOutputStream.close(ContentLengthOutputStream.java:100)
at org.apache.http.impl.entity.EntitySerializer.serialize(EntitySerializer.java:123)
at org.apache.http.impl.AbstractHttpClientConnection.sendRequestEntity(AbstractHttpClientConnection.java:271)
at org.apache.http.impl.conn.ManagedClientConnectionImpl.sendRequestEntity(ManagedClientConnectionImpl.java:197)
at org.apache.http.protocol.HttpRequestExecutor.doSendRequest(HttpRequestExecutor.java:257)
at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:125)
at org.apache.http.impl.client.DefaultRequestDirector.tryExecute(DefaultRequestDirector.java:715)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:520)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:805)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:784)
at com.demeter.server.cloud.ServerPushTaskToCloudService.pushTaskFileToCloud(ServerPushTaskToCloudService.java:90)
at com.demeter.server.cloud.ServerPushTaskToCloudService.main(ServerPushTaskToCloudService.java:105)
通過上網查詢,大致原因是,客戶端和服務端鏈接中斷,但是還在讀寫,所以出現這種問題
一開始以爲是計時器的原因,但是後來不用計時器照樣出現這個錯誤,所以問題肯定是出現在post請求這,沒有辦法,通過抓包工具看了看http報文,如下:
發現,File-Path 值多了個回車換行,然後去掉這個請求頭,錯誤沒在出現。定位到問題後,接下來一點點測試,發現問題出現的原因是,Base64加密後,會在76個字符後面默認加上/r/n,就是多出的這個/r/n,導致請求一直失敗。最後在加密算法中,去掉/r/n,請求順利完成。