场景:
文件服务器的接口如下
@ApiResponses({ @ApiResponse(code = 200, message = "文件上传成功"), @ApiResponse(code = 120, message = "文件上传失败") })
@RequestMapping(value = "/upload", method = RequestMethod.POST)
public ResultData<?> fileUpload(@ApiParam(value = "上传的文件", required = true) MultipartFile uploadFile, String sig) {
......省略
}
如上图,上传文件接口需要两个参数,uploadFile文件类型参数和sig普通数据类型参数。这就涉及到了HTTP基础,HTTP请求分为了消息头和消息体,头信息里面的Content-Type字段定义了消息体的请求格式,SpringMvc是按照请求头来解析消息内容的。
文件的请求头必须是multipart/form-data,而普通数据类型这里定为application/json。怎么兼容呢,这里提供一个解决思路:
构造两个ContentType,文件用文件流传输,请求头为multipart/form-data;
普通数据类型用字节流传输,请求头为application/json;
构造完放入放入一个httpEntity实例中发起请求
代码如下:
@RequestMapping(value="/img/upload",method = RequestMethod.POST)
public ResultObject<?> imgUpload(@ApiParam(value="上传的文件",required=true) MultipartFile uploadFile) throws Exception {
if(uploadFile == null ) {
logger.error(ResponseCode.UPLOAD_NULL_EXCEPTION.msg);
return ResultUtils.error(ResponseCode.UPLOAD_NULL_EXCEPTION);
}
if (uploadFile.getSize() >= Integer.valueOf(maxImg)*1024*1024) {
logger.error(ResponseCode.UPLOAD_OVER_LIMIT_EXCEPTION.msg);
return ResultUtils.error(ResponseCode.UPLOAD_OVER_LIMIT_EXCEPTION);
}
if (uploadFile.getSize() < Integer.valueOf(1024)) {
logger.error(ResponseCode.DELETE_LOW_LIMIT_EXCEPTION.msg);
return ResultUtils.error(ResponseCode.DELETE_LOW_LIMIT_EXCEPTION);
}
String requestUrl = host + ":" + port + "/file/upload";
Map<String, String> resultMap = new HashMap<String, String>();
CloseableHttpClient httpClient = HttpClients.createDefault();
String result = "";
try {
HttpPost httpPost = new HttpPost(requestUrl);
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setCharset(java.nio.charset.Charset.forName("UTF-8"));
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
// 文件传输http请求头(multipart/form-data)
builder.addBinaryBody("uploadFile", uploadFile.getInputStream(), ContentType.MULTIPART_FORM_DATA,
uploadFile.getOriginalFilename());// 文件流
// 字节传输http请求头(application/json)
ContentType contentType = ContentType.create("application/json", Charset.forName("UTF-8"));
builder.addTextBody("sig", sig, contentType);//字节流
HttpEntity entity = builder.build();
httpPost.setEntity(entity);
HttpResponse response = httpClient.execute(httpPost);
// 执行提交
HttpEntity responseEntity = response.getEntity();
resultMap.put("scode", String.valueOf(response.getStatusLine().getStatusCode()));
resultMap.put("data", "");
if (responseEntity != null) {
// 将响应内容转换为字符串
result = EntityUtils.toString(responseEntity, java.nio.charset.Charset.forName("UTF-8"));
resultMap.put("data", result);
}
JSONObject jsonObj = JSONObject.parseObject(result);
if (jsonObj.getString("code").equals("0")) {
return ResultUtils.success(jsonObj.getString("data"),ResponseCode.OK);
} else {
return ResultUtils.error(jsonObj.getString("msg"),ResponseCode.UPLOAD_FILE_FAIL_EXCEPTION);
}
} catch (Exception e) {
resultMap.put("scode", "error");
resultMap.put("data", "HTTP请求出现异常: " + e.getMessage());
resultMap.put("msg", "HTTP请求出现异常:连接到文件服务器失败 ");
Writer w = new StringWriter();
e.printStackTrace(new PrintWriter(w));
return ResultUtils.error(resultMap.get("msg"),ResponseCode.FAIL);
} finally {
try {
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
所需maven依赖
<!--fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.8</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpcore -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
<version>4.4.10</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.6</version>
</dependency>