java后端通过httpclient上传文件
情况描述:
前端--->我的后端代码--->真正的上传后端
代码实现:
---------------------------
前端调用:通过postman进行模拟前端调用实现
说明:调用参数写在body里面的类型为form-data,可以选择参数类型Test/File,其中一般的参数类型为test,文件的参数类型为file,然后选择要上传的文件。调用我的后端链接地址。
我的后端的controller代码:
@RestController
public class UploadController{
@Autowired
private UploadService uploadService;
@PostMapping("upload")
public Object upload(MultipartFile multipartFile, HttpServletRequest request, HttpServletResponse response){
//multipartFile为上传的文件
String data = "";
// form-data中其他参数的处理
Map<String,String[]> map = request.getParameterMap();
data = JSON.toJSONString(map);
return uploadService.upload(multipartFile,data,request,response);
}
}
---------------------------
service实现代码:
@Slf4j
@Service //注意这里的注解是Springboot的注解
public class UploadService{
public Object upload(MultipartFile file, String data, HttpServletRequest request, HttpServletResponse response){
String url = "";//访问的真正的后端的链接地址
String result = "";
CloseableHttpClient client = HttpClients.createDefault();
HttpPost httpPost = new HttpPost(url);
// Header header = new BasicHeader("Content-type","multipart/form-data"); 此处不需要再额外添加头部信息,会自动添加好的
//处理文件 后面的setMode是用来解决文件名称乱码的问题:以浏览器兼容模式运行,防止文件名乱码。
MultipartEntityBuilder builder = MultipartEntityBuilder.create().setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
try{
builder.setCharset(Charset.forName("UTF-8")).addBinaryBody("multipartFile", file.getInputStream(), ContentType.MULTIPART_FORM_DATA, file.getOriginalFilename());
// 处理其他参数
Map map = (Map)JSON.parse(data);
for(Object obj : map.entrySet()){
Map.Entity entity = (Map.Entity) obj;
builder.setTextBody((String) entity.getKey(), (String)((JSONArray)medium.getValue()).get(0));
}
HttpEntity httpEntity = builder.build();
httpPost.setEntity(httpEntity);
HttpResponse httpResponse = client.execute(httpPost);
HttpEntity responseEntity = response.getEntity();
if (responseEntity != null) { // 将响应内容转换为字符串
result= EntityUtils.toString(responseEntity, Charset.forName("UTF-8"));
log.info("上传文件返回结果:{}", result);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
httpClient1.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return result;
}
----------------------------
上面已经完成了从前端调用到后端httpClient调用真正的实现。
说些别的:
我查阅资料以及到编码实现到测试,耗费约1天时间。结果发现中间加了个过渡层去处理文件的上传的问题,还是存在一些弊端。还不如是直接从前端调用真正的上传的接口进行上传的操作。原因:因为上传过程本来就是漫长的过程,httpClient容易超时导致上传失败,而且从前端的角度来看,上传过程,直到上传完成之后,前端才能拿到结果,而且存在httpClient超时的问题导致文件上传失败。所以能避免采用这种方式就尽量不要使用这种方式。
我的想法:我们可以通过鉴权的方式,来直接让前端访问真正的上传后端。