客戶端代碼
/*
* @param picPaths 需要上傳的文件路徑集合
*
* @param requestURL 請求的url
*
* @return 返回響應的內容
*/
public static void uploadFile(String[] picPaths, String requestURL) {
String boundary = UUID.randomUUID().toString(); // 邊界標識 隨機生成
String prefix = "--", end = "\r\n";
String content_type = "multipart/form-data"; // 內容類型
String CHARSET = "utf-8"; // 設置編碼
int TIME_OUT = 10 * 10000000; // 超時時間
try {
URL url = new URL(requestURL);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(TIME_OUT);
conn.setConnectTimeout(TIME_OUT);
conn.setDoInput(true); // 允許輸入流
conn.setDoOutput(true); // 允許輸出流
conn.setUseCaches(false); // 不允許使用緩存
conn.setRequestMethod("POST"); // 請求方式
conn.setRequestProperty("Charset", "utf-8"); // 設置編碼
conn.setRequestProperty("connection", "keep-alive");
conn.setRequestProperty("Content-Type", content_type + ";boundary=" + boundary);
/**
* 當文件不爲空,把文件包裝並且上傳
*/
OutputStream outputSteam = conn.getOutputStream();
DataOutputStream dos = new DataOutputStream(outputSteam);
for (int i = 0; i < picPaths.length; i++) {
File file = new File(picPaths[i]);
StringBuffer sb = new StringBuffer();
sb.append(prefix);
sb.append(boundary);
sb.append(end);
/**
* 這裏重點注意: name裏面的值爲服務器端需要key 只有這個key 纔可以得到對應的文件
* filename是文件的名字,包含後綴名的 比如:abc.png
*/
sb.append("Content-Disposition: form-data; name=\"" + "multipartFiles" + "\"; filename=\"" + file.getName() + "\"" + end);
sb.append("Content-Type: application/octet-stream; charset=" + CHARSET + end);
sb.append(end);
dos.write(sb.toString().getBytes());
InputStream is = new FileInputStream(file);
byte[] bytes = new byte[8192];// 8k
int len = 0;
while ((len = is.read(bytes)) != -1) {
dos.write(bytes, 0, len);
}
is.close();
dos.write(end.getBytes());// 一個文件結束標誌
}
byte[] end_data = (prefix + boundary + prefix + end).getBytes();// 結束
// http
// 流
dos.write(end_data);
dos.flush();
/**
* 獲取響應碼 200=成功 當響應成功,獲取響應的流
*/
int res = conn.getResponseCode();
if(res == 200) {
InputStream is = conn.getInputStream();
int ch;
StringBuffer b = new StringBuffer();
while ((ch = is.read()) != -1) {
b.append((char) ch);
}
String s = b.toString();
System.out.println(s);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
服務器端
@RequestMapping(value="imgUploads",method=RequestMethod.POST)
@ResponseBody
public Result upload(@RequestParam(required=true)MultipartFile[] multipartFiles,HttpServletRequest request){
ResultData data = new ResultData();
List<Map<String,Object>> images = new ArrayList<Map<String,Object>>();
try {
for(int i = 0; i < multipartFiles.length; i++) {
MultipartFile multipartFile = multipartFiles[i];
log.info("文件長度: " + multipartFile.getSize());
log.info("文件類型: " + multipartFile.getContentType());
log.info("文件名稱: " + multipartFile.getName());
log.info("文件原名: " + multipartFile.getOriginalFilename());
byte[] bytes = multipartFile.getBytes();
String type = FilenameUtils.getExtension(multipartFile.getOriginalFilename());
ResultMsg msg = upload(bytes, type); //你的服務端上傳代碼
//上傳成功,保存Image數據
if (msg.isResult()) {
Map<String,Object> dataMap = new HashMap<String,Object>();
dataMap.put("filePath", msg.getMsg());//原圖url
//擴展文件信息,可選(如需使用可以客戶端獲取)
dataMap.put("size", multipartFile.getSize());
dataMap.put("contentType", multipartFile.getContentType());
dataMap.put("originalFilename", multipartFile.getOriginalFilename());
images.add(dataMap);
}
}
} catch (Exception e) {
log.error("批量上傳圖片失敗:" + e.getMessage(),e.getMessage());
}
data.put("msg", "圖片上傳成功!");
data.put("results", images);
return new Result(data);
}
調用示例
@Test
public void testUpload() {
String[] uploadFiles = {"C:\\Users\\wang-lei\\Desktop\\image\\1.png",
"C:\\Users\\wang-lei\\Desktop\\image\\150_75_1.png",
"C:\\Users\\wang-lei\\Desktop\\image\\280_500.png"};
String requestURL = "http://api.local.net/api/common/upload/imgUploads.json";
UploadImagesTestCase2.uploadFile(uploadFiles, requestURL);
}
返回數據示例
{
"code": 0,
"message": "成功",
"serverTime": 1471402446400,
"data": {
"subCode": 0,
"subMessage": null,
"results": [
{
"filePath": "0fb619de-3816-4b9c-ace6-1c6508795d5d.png",
"originalFilename": "1.png",
"contentType": "image/png",
"size": 249635
},
{
"filePath": "6fcb3131-8901-41ac-87f9-5fa9f453a7f6.png",
"originalFilename": "150_75_1.png",
"contentType": "image/png",
"size": 17747
},
{
"filePath": "a18819c8-fc93-40d8-bbde-72111a5c872b.png",
"originalFilename": "280_500.png",
"contentType": "image/png",
"size": 201269
}
],
"msg": "圖片上傳成功!"
}
}
總結
衆所周知瀏覽器上傳圖片時一般都是一個Form表單中要使用<input type='file' name='file' />來選擇上傳的文件,並上傳,代碼如下:
<html>
<head>
<title>upload</title>
<meta http-equiv="description" content="this is my page">
<meta http-equiv="content-type" content="text/html; charset=GB18030">
</head>
<body>
<form action="servlet/UploadFile" method="post"
enctype="multipart/form-data">
<input type="file" name="file1" id="file1" />
<input type="file" name="file2" id="file2" />
<input type="submit" value="上傳" />
</form>
</body>
</html>
從上面的代碼可以看出,有兩個文件選擇框(file1和file2),在上傳文件時,<form>標籤必須加上enctype="multipart/form-data",否則瀏覽器無法將文件內容上傳到服務端。
到底這個post請求向服務端發送了什麼信息?從瀏覽器中可以看到以下請求信息:
有了這些信息就可以使用HttpClient 拼接好請求串來模擬瀏覽器上傳圖片文件到服務器了,剩下的工作就是接收這些圖片的字節流處理。