接口间传输文件流
1、业务背景
外部服务请求文件信息,通过对外暴露的前置服务,请求到应用服务器上,应用服务器从文件存储平台下载文件,并返回文件流给外部服务。请求流程如下:
这里我们做个简化,假设文件存储在了应用服务器中,前置服务、应用服务在同一台服务器上。
2、代码实现
2.1、pom依赖
1 <parent> 2 <groupId>org.springframework.boot</groupId> 3 <artifactId>spring-boot-starter-parent</artifactId> 4 <version>2.1.6.RELEASE</version> 5 </parent> 6 <dependencies> 7 <dependency> 8 <groupId>org.springframework.boot</groupId> 9 <artifactId>spring-boot-starter-web</artifactId> 10 </dependency> 11 <dependency> 12 <groupId>org.springframework.boot</groupId> 13 <artifactId>spring-boot-starter-test</artifactId> 14 </dependency> 15 <dependency> 16 <groupId>org.apache.httpcomponents</groupId> 17 <artifactId>httpclient</artifactId> 18 <version>4.5.13</version> 19 </dependency> 25 26 <!-- Java集合增强 --> 27 <dependency> 28 <groupId>commons-collections</groupId> 29 <artifactId>commons-collections</artifactId> 30 <version>3.2.2</version> 31 </dependency> 32 <!-- 通用工具包 --> 33 <dependency> 34 <groupId>org.apache.commons</groupId> 35 <artifactId>commons-lang3</artifactId> 36 <version>3.8.1</version> 37 </dependency> 38 </dependencies>
2.2、汇总实现
1 import org.springframework.stereotype.Controller; 2 import org.springframework.web.bind.annotation.PathVariable; 3 import org.springframework.web.bind.annotation.RequestMapping; 4 import javax.servlet.ServletOutputStream; 5 import javax.servlet.http.HttpServletResponse; 6 import java.io.*; 7 import java.net.HttpURLConnection; 8 import java.net.URL; 9 import java.net.URLConnection; 10 11 12 @Controller 13 public class FileStreamController { 14 15 /** 前置服务的实现 16 * 前置服务接收获取文件请求 17 * @param fileName 文件名称 18 * @param resp 响应 19 * @throws Exception 20 */ 21 @RequestMapping("/front/file/{fileName}") 22 public void getFile(@PathVariable("fileName") String fileName, HttpServletResponse resp) throws Exception { 23 // 应用服务地址 24 String appurl = "http://localhost:8085/download/" + fileName; 25 26 int connectTimeOut = Integer.valueOf(30000); 27 int readTimeOut = Integer.valueOf(100) * 1000; 28 29 HttpURLConnection httpUrlConnection = null; 30 URL url = null; 31 InputStream inStrm = null; 32 try{ 33 url = new URL(appurl); 34 URLConnection rulConnection = url.openConnection(); 35 // 设置连接超时时间 36 rulConnection.setConnectTimeout(connectTimeOut); 37 // 设置读超时时间 38 rulConnection.setReadTimeout(readTimeOut); 39 httpUrlConnection = (HttpURLConnection) rulConnection; 40 // 开启向服务器发送信息标志 41 httpUrlConnection.setDoOutput(true); 42 // 开启从服务器获取信息标志 43 httpUrlConnection.setDoInput(true); 44 // 关闭关村 45 httpUrlConnection.setUseCaches(false); 46 // 请求类型 47 httpUrlConnection.setRequestProperty("Content-Type", "text/xml;charset=utf-8"); 48 // 请求方式 49 httpUrlConnection.setRequestMethod("POST".toUpperCase()); 50 51 // 获取应用服务的输入流 52 inStrm = httpUrlConnection.getInputStream(); 53 54 //设置响应头类型 55 resp.setContentType("multipart/form-data"); 56 //设置响应头打开方式,并设置下载时的文件名称 57 resp.setHeader("content-disposition","attachment;filename=" + fileName); 58 // 获取响应的输出流,输出到浏览器 59 ServletOutputStream sos = resp.getOutputStream(); 60 byte[] buffer = new byte[1024]; 61 int length = 0; 62 while((length = inStrm.read(buffer)) != -1){ 63 sos.write(buffer,0,length); 64 sos.flush(); 65 } 66 sos.close(); 67 inStrm.close(); 68 }catch (Exception ex) { 69 ex.printStackTrace(); 70 } 71 } 72 73 /** 应用服务的实现 74 * 应用服务获取文件 75 * @param fileName 文件名称 76 * @param response 响应 77 * @return 78 * @throws Exception 79 */ 80 @RequestMapping("/download/{fileName}") 81 public HttpServletResponse downloadFile(@PathVariable("fileName") String fileName, HttpServletResponse response) throws Exception { 82 // 指定文件地址,这里假设目标文件存储在D盘 83 String filePath = "D:\\" + fileName; 84 // 获取文件输入流 85 FileInputStream inputStream = new FileInputStream(new File(filePath)); 86 // 将文件流传输到前置服务 87 byte[] buffer = new byte[1024]; 88 int len; 89 ServletOutputStream outputStream = response.getOutputStream(); 90 while ((len = inputStream.read(buffer)) != -1) { 91 outputStream.write(buffer, 0 , len); 92 outputStream.flush(); 93 } 94 return response; 95 96 } 97 98 }
2.3、配置文件及启动类
2.3.1、配置文件
server:
port: 8085
2.3.2、启动类
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class FileStreamApplication { public static void main(String[] args) { SpringApplication.run(FileStreamApplication.class, args); } }
3、测试
3.1、在D盘上准备好要下载的文件
这里我在D盘上准备了要下载的Test压缩包Test.tar.gz。
3.2、启动服务浏览器请求前置服务下载文件
文件下载完成。