赞
踩
需求是这样的:
公司的图片服务器在 OSS 上,前端拿到地址就可以访问 图片文件
前端需要将已经发送给OSs的图片,重新发送给第三方系统,前端只可以传图片路径,后台需要这个路径从OSs 获取文件流(InputStream 对象),然后 直接将这个流对象 返给ftp 服务器(没错第三方系统用的就是 ftp 协议)
但是实际检验发现行不通:
调用A系统 实际返回结果:
A系统代码如下:
原因:
InputStream 这个对象很特殊,不像 Student 这些实体类有自己的属性,计算机系统之间交互的时候可以通过序列号,另一台机器就可以拿到属性值一样的对象,而 InputStream 对象没有自己的属性,他属于流对象 ,另一台机器要拿到相同 的流对象,不可以直接返回 InputStream 接口子类的实例,而是要 把流里的字节内容 通过 输出流 传给另一台机器。
案例:
搭建两个简单的springboot 项目
服务提供者 端口是 8091
服务消费者端口是 8092
请求方式 用 Spring 提供的
RestTemplate 发送请求
注意:
RestTemplate springboot 不会自动装配,需要手动装配
服务消费者启动类:
- @SpringBootApplication
- //@MapperScan({"com.example.demo.mapper","com.example.demo.mapper"})
- // @MapperScan 代替 @Mapper的
- @MapperScan("com.example.demo.mapper")
- // 开启缓存
- @EnableCaching
- public class DemoApplication {
- public static void main(String[] args) {
- SpringApplication.run(DemoApplication.class, args);
- }
-
- @Bean
- RestTemplate restTemplate(){
- return new RestTemplate();
- }
-
- }
先看效果图:
需求:
向 系统B 传入 文件 path ,系统B 通过 RestTemlate 向系统A发送请求,系统A根据 path 得到 InputStream 流(这个流在系统A里,不能直接返给 B,这样B拿不到 流),系统A将 InputStream的内容写入到 输出流里,并刷给 系统B,系统B 就这样得到 系统A的输出流(对于B 就是输入流,B读取A的输出流)
① path 为图片:
E:\\test1\\doc\\郑宇_20200908162125_退款确认书_032CE223-AB92-4F68-A1A6-91CAF06F7051.JPG
返回结果:
② path 为PDF 文件
不能预览,需要下载查看
代码如下:
服务提供者:
- /**
- * @Description: 单文件上传
- * @Param: List<MultipartFile> files = ((MultipartHttpServletRequest) request).getFiles("files");
- * @return:
- * @Author: guoyiguang
- * @Date:
- */
- @PostMapping("/ftpFileUpload/upload2")
- @ResponseBody
- public void upload2(HttpServletRequest request,HttpServletResponse response){
-
- // 获取请求消费者参数
- String path = request.getParameter("path");
-
- FileInputStream inputStream = null;
- OutputStream output = null;
- if (StringUtils.isEmpty(path)){
- System.out.println("path is empty");
- return;
- }
- //服务器端
- try {
-
- //注意: 得到 inputStream 后,不能直接 return inputStream , 消费者是拿不到的 InputStream 这个对象的
- //InputStream inputStream = files.get(0).getInputStream();
- // FileInputStream inputStream = new FileInputStream("E:\\test1\\doc\\郑宇_20200908162125_退款确认书_032CE223-AB92-4F68-A1A6-91CAF06F7051.JPG");
- // inputStream = new FileInputStream("E:\\test1\\pdf\\LeetCode 101 - A LeetCode Grinding Guide (C Version).PDF");
- inputStream = new FileInputStream(path);
- // 将输入流转化为 输出流 传给消费者,供消费者消费
- output = response.getOutputStream();
-
-
- byte[] bts = new byte[8192];
- int len = -1;
- while((len=inputStream.read(bts))!=-1){
- output.write(bts,0,len);
- }
-
- response.setHeader("topic","stream 测试");
- // 返给客户端
- output.flush();
- } catch (IOException e) {
- System.out.println("io exception");
- }finally {
-
- if(null != inputStream){
- try {
- inputStream.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
-
- }
-
- //
- if(null != output){
- try {
- output.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
-
- }
- }
-
-
- }
服务消费者:
- package com.example.demo.controller;
-
-
- import lombok.extern.slf4j.Slf4j;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.core.io.Resource;
- import org.springframework.http.*;
- import org.springframework.stereotype.Controller;
- import org.springframework.util.LinkedMultiValueMap;
- import org.springframework.util.MultiValueMap;
- import org.springframework.web.bind.annotation.PostMapping;
- import org.springframework.web.client.RestTemplate;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.OutputStream;
-
- /**
- * @program: springboot_01
- * @description: 文件上传工具类 ftpFileUpload/upload
- * @author: guoyiguang
- * @create: 2021-06-25 11:50
- **/
- @Controller
- @Slf4j
- public class FtpFileUploadController {
-
- @Autowired
- private RestTemplate restTemplate;
-
-
-
-
- /**
- * @Description: 单文件上传
- * @Param: List<MultipartFile> files = ((MultipartHttpServletRequest) request).getFiles("files");
- * @return:
- * @Author: guoyiguang
- * @Date:
- */
- @PostMapping("/ftpFileUpload/upload")
- public void upload(HttpServletRequest request,HttpServletResponse response){
-
- String path = request.getParameter("path");
-
-
- String robotUrl = "http://192.168.43.161:8091/ftpFileUpload/upload2" ;
-
- HttpHeaders headers = new HttpHeaders();
- headers.setContentType(MediaType.APPLICATION_JSON);
-
-
- MultiValueMap<String, String> requestEntity = new LinkedMultiValueMap<>();
- requestEntity.add("path", path);
- // 调用B 系统 获取输入流(获取流对象,要用 org.springframework.core.io.Resource 对象接收)
- ResponseEntity<Resource> entity = restTemplate.postForEntity(robotUrl, requestEntity, Resource.class);
- InputStream inputStream = null ;
- OutputStream output = null;
- try {
-
- inputStream = entity.getBody().getInputStream();
- int count = 0;
- // 能否使用取决于实现了InputStream这个抽象类的具体子类中有没有实现available这个方法。如果实现了那么就可以取得大小,如果没有实现那么就获取不到。例如FileInputStream就实现了available方法,那么就可以用new byte[in.available()];这种方式。但是,网络编程的时候Socket中取到的InputStream,就没有实现这个方法,那么就不可以使用这种方式创建数组
- // 在进行网络操作时往往出错,因为你调用available()方法时,对发发送的数据可能还没有到达,你得到的count是0。
- while (count == 0) {
- count = inputStream .available();
- }
- output = response.getOutputStream();
-
- byte[] bts = new byte[8192];
- int len = -1;
- while((len=inputStream.read(bts))!=-1){
- output.write(bts,0,len);
- }
-
- response.setHeader("topic2","stream 测试2");
- // 返给客户端输出流
- output.flush();
-
- } catch (IOException e) {
- e.printStackTrace();
- }finally {
- if(null != inputStream){
- try {
- inputStream.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
-
- }
-
- if(null != output){
- try {
- output.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
-
- }
-
- }
-
- }
-
- }
如果是在StringCloud中,各系统之间是通过 Feign 接口调用的,那么怎么实现呢?
Feign 接口返回流:
服务提供者 是输出流数据 给服务消费者,用输出流
服务消费者是要 读取流,用 输入流
代码如下:
参考链接:https://www.debug8.com/java/t_22044.html
服务提供者:
- @GetMapping("getPictureByPath")
- public void queryJobInfoLogDetail(@RequestParam String path, HttpServletResponse response) {
-
- File file = new File(path);
- InputStream fileInputStream = new FileInputStream(file);
- // 说明:如果是 Linux 上,则换成 Linux 上所在的目录
- // 等同于 FileInputStream inputStream = new FileInputStream("E:\\test1\\do\\郑_20200908162125_退款确认书_032CE223-AB92-4F68-A1A6-91CAF06F7051.JPG");
- OutputStream outStream;
- try {
- outStream = response.getOutputStream();
-
- byte[] bytes = new byte[1024];
- int len = 0;
- while ((len = inputStream.read(bytes)) != -1) {
- outStream.write(bytes, 0, len);
- }
- fileInputStream.close();
- outStream.close();
- outStream.flush();
- } catch (IOException e) {
- log.error("exception", e);
- }
- }
消费端:
feign
- @GetMapping(value = "/getPictureByPath", consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
- feign.Response getPictureByPath(@PathVariable("path") String path);
服务消费端:
- @GetMapping("/getPictureByPath")
- public void getPictureByPath(@RequestParam String path, HttpServletResponse servletResponse) {
-
- // 消费端 调用 feign 接口
- Response response = apiServices.getPictureByPath(path);
- Response.Body body = response.body();
-
- InputStream fileInputStream = null;
- OutputStream outStream;
- try {
- fileInputStream = body.asInputStream();
- outStream = servletResponse.getOutputStream();
-
- byte[] bytes = new byte[1024];
- int len = 0;
- while ((len = fileInputStream.read(bytes)) != -1) {
- outStream.write(bytes, 0, len);
- }
- fileInputStream.close();
- outStream.close();
- outStream.flush();
- } catch (Exception e) {
-
- }finally{
- // 关闭流
-
- }
- }
用最原始的方法读取流对象: HttpURLConnection
- static void update() throws IOException {
- URL url = new URL("http://172.16.59.129:8000/update/test.so");
- HttpURLConnection conn = (HttpURLConnection) url.openConnection();
- if(conn.getResponseCode() == 200) {
- int totalLength = conn.getContentLength();
- BufferedInputStream in = new BufferedInputStream(conn.getInputStream());
- byte[] buffer = new byte[512];
- int readLength = 0;
- int length = 0;
- while((length=in.read(buffer)) != -1) {
- readLength += length;
- //进度条
- System.out.println(((float)readLength) /((float)(totalLength)));
- }
- }
- }
方案二: 或者直接返回 字节数组
- private ByteArrayOutputStream memoryOutputStream;
-
- public byte[] getData()
- {
- if (memoryOutputStream != null)
- {
- return memoryOutputStream.toByteArray();
- }
- return null;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。