springboot文件中转(接收MultipartFile转File、后台HttpClient发送带文件的multipart/form-data请求)

项目服务有时候需要接收前端传来的文件再转给第三方接口,在这过程中能在本地接口做身份验证、参数调整等工作,也让前端用户的文件有机会发给只有专用网络才能访问到的服务。

要点

1、接收与保存本地文件

接收后保存在本地的操作,会给每个文件都创建一个不重复的目录,保证并发或重名时不被占用和覆盖。文件复制可以用MultipartFile的 transferTo(File) 方法来做。

2、用HttpClient发送form-data格式的带文件请求。

这里用到的包是org.apache.commons.httpclient系列,请求实体用MultipartRequestEntity对象,其中的字符串型数据用StringPart, 文件用FilePart。
需要注意的是,为了保证传输中文名的文件在接收端那边字符正确,需要重写PostMethod的getRequestCharSet方法以及FilePart的sendDispositionHeader方法,

实现

先用postman工具测试最终需要接收文件的接口,以form-data的格式发送带文件与其他参数的post请求,确认最终接口能正常接收文件与响应。
在这里插入图片描述

下面提供springboot接收前端文件数据,并以form-data形式发给第三方接口的示例。

	@ResponseBody
	@RequestMapping(value="/fileForward", produces="application/json;charset=UTF-8")
	public String fileForward(MultipartFile file, String resourceType, HttpServletRequest request) {
		String tmpFileDir = null;
		String fileName = null;
		File dirFile = null;
		File localFile = null;
		try {
			log.info("资源类型: : " + resourceType);
			
			//制作每个文件特有的目录,保证并发或重名时不出问题
			String randomFileName = UUID.randomUUID().toString();
			tmpFileDir = "D:/tmp/tmpFile/"+randomFileName;
			dirFile = new File(tmpFileDir);
			if(!dirFile.exists()) {
				dirFile.mkdirs();
			}
			//MultipartFile转成File对象
			fileName = tmpFileDir+"/"+file.getOriginalFilename();
			localFile = new File(fileName);
			file.transferTo(localFile);
			
	        HttpClient client = new HttpClient();
	        //文件传输可能受带宽影响导致时间太长,慎用。
//	        client.getHttpConnectionManager().getParams().setConnectionTimeout(3000);
//	        client.getHttpConnectionManager().getParams().setSoTimeout(3000);
	        
			//转发的地址,可以根据需要从配置文件中读
			String url = "http://127.0.0.1:9006/upload/resource/upload";
	        //覆盖PostMethod的getRequestCharSet,返回为UTF-8
	        PostMethod postMethod=new PostMethod(url) {
	        	public String getRequestCharSet() {
	        		return "UTF-8";
	        	}
	        };
	        
	        //请求参数里的文件
	        FilePart fp = new FilePart("file", localFile) {
	    	    protected void sendDispositionHeader(OutputStream out) throws IOException {
	                //实现父类super.sendDispositionHeader(out)的逻辑
	                out.write(CONTENT_DISPOSITION_BYTES);
	                out.write(QUOTE_BYTES);
	                out.write(EncodingUtil.getBytes(getName(),"utf-8"));
	                out.write(QUOTE_BYTES);
	                String fileName = getSource().getFileName();
	                // 解决中文文件名乱码
	                if (!StringUtils.isEmpty(fileName)){
	                    out.write(EncodingUtil.getAsciiBytes(FILE_NAME));
	                    out.write(QUOTE_BYTES);
	                    out.write(EncodingUtil.getBytes(fileName,"utf-8"));
	                    out.write(QUOTE_BYTES);
	                }
	    	    }
	        };
	        
	        //请求参数数组
			Part[] parts = {new StringPart("resourceType", resourceType), fp};
			RequestEntity requestEntity = new MultipartRequestEntity(parts, postMethod.getParams());
			postMethod.setRequestEntity(requestEntity);
			
	        int resultCode = client.executeMethod(postMethod);
	        if(resultCode == 200){
				log.info("第三方接口返回: " + postMethod.getResponseBodyAsString());
	            return postMethod.getResponseBodyAsString();
	        }else{
	            return "发送第三方接口出错:" + postMethod.getResponseBodyAsString();
	        }
			
		} catch (Exception e) {
			log.error("文件转发出错:" + e.getMessage(), e);
			return "文件转发出错:" + e.getMessage();
		} finally {
			//根据需要处理存在本地的文件,如压缩、删除等
		}
	}

写完用postman工具请求
在这里插入图片描述
检查自己后台的日志:
在这里插入图片描述
能看到自己的服务成功接收请求,后台请求最终接口也获得了成功的响应。

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值