2025年3月30日 星期日 甲辰(龙)年 月廿九 夜 设为首页 加入收藏
rss
您当前的位置:首页 > 计算机 > 编程开发 > Java

跨项目文件流转发功能实现

时间:02-01来源:作者:点击数:52

需求:文件流从当前项目转发到另外一个项目。

思路:需要拦截请求中的文件流,组装之后转发到另外一个项目中。

效果:

具体步骤如下

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 {
  • @Autowired
  • private 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 {
  • @Override
  • public 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
  • */
  • @Override
  • public 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<FileItem> 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.cdsy.xyz/computer/programme/suggest/230201/cd39995.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 been provided
方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门