跨项目文件流转发功能实现
跨项目文件流转发功能实现
需求:文件流从当前项目转发到另外一个项目。
思路:需要拦截请求中的文件流,组装之后转发到另外一个项目中。
效果:

具体步骤如下:
1.首先读取文件的接口:
api接口:
package com.zxy.demo.api;import com.zxy.demo.service.FileService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;/*** FileUpload** @author zhouxy@133.cn* @date 2022/3/1**/
@RestController
@RequestMapping("/file")
@Slf4j
public class FileUploadController {@Autowiredprivate FileService fileService;@PostMapping("/upload")public String test(@RequestParam("file") MultipartFile file) {fileService.uploadFile(file);return "成功";}
}
package com.zxy.demo.service.impl;import com.zxy.demo.service.FileService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;/*** FileServiceImpl** @author zhouxy@133.cn* @date 2022/3/1**/
@Slf4j
@Service
public class FileServiceImpl implements FileService {@Overridepublic void uploadFile(MultipartFile file) {try (InputStream is = file.getInputStream();InputStreamReader isReader = new InputStreamReader(is);BufferedReader br = new BufferedReader(isReader);) {log.info("文件打印:");while (br.ready()) {log.info("{}", br.readLine());}} catch (IOException e) {e.printStackTrace();}}
}
2.调用方代码:
package com.zxy.demo.config;import lombok.extern.slf4j.Slf4j;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.protocol.HttpDateGenerator;
import org.apache.http.util.EntityUtils;
import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.List;/*** InterceptorConfig** @author zhouxy@133.cn* @date 2022/3/3**/
@Slf4j
public class InterceptorConfig implements HandlerInterceptor {private static final CloseableHttpClient httpclient;static {//创建http客户端httpclient = HttpClients.custom().useSystemProperties().setRetryHandler(new DefaultHttpRequestRetryHandler(3, true)).build();}/*** 进入controller层之前拦截请求** @param request* @param httpServletResponse* @param o* @return* @throws Exception*/@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse httpServletResponse, Object o) throws Exception {log.info("");String url = request.getRequestURI();String newUrl = "http://localhost:8081/file/upload";if (url.contains("/file/upload")) {String result = null;/*1.第一种读取流方式*/MultipartEntityBuilder builder = readFile(request);result = postResultMultipartFile(newUrl, builder, "文件上传");/*2.第二种读取流方式*//*InputStreamEntity inputStreamEntity = new InputStreamEntity(request.getInputStream(), request.getContentLength(), ContentType.parse(request.getContentType()));result = postResultMultipartFile(newUrl, inputStreamEntity, "文件上传");*/log.info("result====>{}", result);return false;}return true;}/*** post请求接口** @Author zhouxy*/public String postResultMultipartFile(String url, HttpEntity httpEntity, String actionDesc) {HttpEntity responseEntity;try {HttpPost httpPost = new HttpPost(url);httpPost.setEntity(httpEntity);RequestConfig config = RequestConfig.custom().setConnectTimeout(3000).build();httpPost.setConfig(config);log.info("lenght:{}", httpEntity.getContentLength());HttpResponse response = httpclient.execute(httpPost);// 执行提交responseEntity = response.getEntity();if (responseEntity != null) {log.info("responseEntity:{}", responseEntity);// 将响应内容转换为字符串return EntityUtils.toString(responseEntity, Charset.forName("UTF-8"));}} catch (IOException e) {log.error(actionDesc + ":IOException:", e.getMessage());} catch (Exception e) {log.error(actionDesc + ":Exception:", e.getMessage());}return null;}/*** 读取文件** @param request* @return*/private MultipartEntityBuilder readFile(HttpServletRequest request) {MultipartEntityBuilder builder = MultipartEntityBuilder.create();builder.setCharset(Charset.forName("utf-8"));builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);//加上此行代码解决返回中文乱码问题FileItemFactory factory = new DiskFileItemFactory();ServletFileUpload upload = new ServletFileUpload(factory);upload.setHeaderEncoding("UTF-8");List list = null;try {list = upload.parseRequest(request);} catch (FileUploadException e) {e.printStackTrace();}log.info("list:{}", list.size());for (FileItem file : list) {//获取文件名(带后缀名)String fileName = file.getName();//获取文件输入流try (InputStream input = file.getInputStream()) {builder.addBinaryBody("file", input, ContentType.MULTIPART_FORM_DATA, fileName);// 文件流} catch (IOException e) {log.error("文件流读取失败:", e);}}return builder;}/*** post请求接口** @Author zhouxy*/public String postResultMultipartFile(String url, MultipartEntityBuilder builder, String actionDesc) {HttpEntity httpEntity;HttpEntity responseEntity;try {HttpPost httpPost = new HttpPost(url);// 添加分销接口默认header,分销新网关凭证httpEntity = builder.build();httpPost.setEntity(httpEntity);HttpResponse response = httpclient.execute(httpPost);// 执行提交log.info("转发成功:");responseEntity = response.getEntity();if (responseEntity != null) {// 将响应内容转换为字符串return EntityUtils.toString(responseEntity, Charset.forName("UTF-8"));}} catch (IOException e) {log.error(actionDesc + ":IOException:", e.getMessage());} catch (Exception e) {log.error(actionDesc + ":Exception:", e.getMessage());}return null;}
}
调用方文件上传接口:
package com.zxy.demo.api;import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;/*** FileUpload** @author zhouxy@133.cn* @date 2022/3/1**/
@RestController
@RequestMapping("/file")
@Slf4j
public class FileUploadController {@PostMapping("/upload")public void test(@RequestParam("file") MultipartFile file) {log.info("1111111");}
}
完成上述代码之后,但是调用upload.parseRequest(request),返回的list的size为0,不能从request中读取文件流。该问题需要修改一下配置文件application.yml(Springboot项目):
spring:servlet:multipart:# 禁用multipart读取文件enabled: false
遇到的问题:
1.读取upload.parseRequest(request)返回size为0的问题,上面已经说了解决办法。
2.刚开始采用的是aop方式,但是获取不到文件。在解决1的问题之后,继续获取,仍然不行。
问题点在于两点:
(1)我没分清aop和拦截器的区别(链接: https://www.cnblogs.com/natian-ws/p/10824363.html),区别如下:
过滤器 过滤器可以拦截到方法的请求和响应(ServletRequest request, SetvletResponse response),并对请求响应做出响应的过滤操作,比如设置字符编码、鉴权操作。拦截器 拦截器可以在方法之前(preHandle)和方法执行之后(afterCompletion)进行操作,回调操作(postHandle),可以获取执行的方法的名称,请求(HttpServletRequest)。AOP切片 AOP操作可以对操作进行横向的拦截,最大的优势在于可以获取执行方法的参数,对方法进行统一的处理,常见使用日志,事务,请求参数安全验证等
(2)MultipartFile的读取流程
MultipartFile读取文件流,是从HttpServletRequest中读取文件流,而request中的流只能读取一次。因此aop做切片,无法从中读取文件流。
使用aop读取文件流会报以下错误。
严重: Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.web.multipart.MultipartException: Failed to parse multipart servlet request; nested exception is java.lang.IllegalStateException: Unable to process parts as no multi-part configuration has been provided] with root cause java.lang.IllegalStateException: Unable to process parts as no multi-part configuration has b
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
