java后端通过httpclient上传文件

情况描述:

前端--->我的后端代码--->真正的上传后端

代码实现:
---------------------------

前端调用:通过postman进行模拟前端调用实现
java后端通过httpclient上传文件
说明:调用参数写在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超时的问题导致文件上传失败。所以能避免采用这种方式就尽量不要使用这种方式。
我的想法:我们可以通过鉴权的方式,来直接让前端访问真正的上传后端。