好久沒發帖了,難的清閒。記錄下幾個坑:
公司使用c++開發了核心功能(貌似有產權),對外開放restful風格的接口。我的項目就是調用這些接口,定製化客戶的具體業務場景。
其中一個接口就是使用post方式發送一個文件,然後它給我們返回一個分析後的信息,如此而已。
由於我們項目用了spring,我當然就嘗試了spring封裝的restTemplate。但發現其他和文件無關的接口,都沒問題。無論post、get、delete。。。。,只有這個文件接口就是失敗。
我心裏打鼓,不會觸及底層http了吧。於是我繼續寫測試案例,做了個java實現的接受文件的服務接口的小項目,再嘗試使用我們項目去調用它,發現一切ok。
這下我蒙了。
最後貼上我使用jdk原生的方案:
/**
* @note 以POST方式上傳文件
*
* @param requestUrl
* @param file
* @return
*/
public static String postUseUrlConnection(String requestUrl, File file) {
String end = "\r\n";
String twoHyphens = "--";
String boundary = "*****"+UUID.randomUUID().toString();
//String newName = "image.jpg";
StringBuffer sb = new StringBuffer();
try {
URL url = new URL(requestUrl);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
// 允許Input、Output,不使用Cache
con.setDoInput(true);
con.setDoOutput(true);
con.setUseCaches(false);
// 設置以POST方式進行傳送
con.setRequestMethod("POST");
// 設置RequestProperty
con.setRequestProperty("Connection", "Keep-Alive");
con.setRequestProperty("Charset", "UTF-8");
con.setRequestProperty("Content-Type",
"multipart/form-data;boundary=" + boundary);
// 構造DataOutputStream流
DataOutputStream ds = new DataOutputStream(con.getOutputStream());
ds.writeBytes(twoHyphens + boundary + end);
// ds.writeBytes("Content-Disposition: form-data; name=\"body\";filename=\"" + file.getName() + "\"" + end);
ds.writeBytes("Content-Disposition: form-data; name=\"body\";filename=\""+UUID.randomUUID().toString()+"\"" + end);
ds.writeBytes(end);
// 構造要上傳文件的FileInputStream流
FileInputStream fis = new FileInputStream(file);
// 設置每次寫入1024bytes
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
int length = -1;
// 從文件讀取數據至緩衝區
while ((length = fis.read(buffer)) != -1) {
// 將資料寫入DataOutputStream中
ds.write(buffer, 0, length);
}
ds.writeBytes(end);
ds.writeBytes(twoHyphens + boundary + twoHyphens + end);
// 關閉流
fis.close();
ds.flush();
// 獲取響應流
InputStream is = con.getInputStream();
int ch;
while ((ch = is.read()) != -1) {
sb.append((char) ch);
}
// 關閉DataOutputStream
ds.close();
return sb.toString();
} catch (Exception e) {
e.printStackTrace();
}
return sb.toString();
}