说明:微服务架构使用springcloud
需求1:A服务是业务,B服务是功能【文件上传】,用户通过浏览器上传文件file,上传访问A服务,A服务调用B服务的上传功能
需求2:A服务是业务,B服务是功能【文件下载】,用户通过浏览器下载文件file,下载访问A服务,A服务调用B服务的下载功能
话不多说,上代码:
A服务【A调用B】:
import com.sys.common.Result; import io.swagger.annotations.*; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.bind.annotation.*; import org.springframework.web.client.RestTemplate; import org.springframework.web.multipart.MultipartFile; import javax.imageio.ImageIO; import javax.servlet.http.HttpServletResponse; import java.awt.image.BufferedImage; import java.io.*; import java.util.Objects; /** * 文件服务 * @author 李庆伟 * @date 2021/8/31 14:53 */ @Slf4j @RequestMapping("web/files") @RestController @Api(value = "文件服务", tags = "文件服务") public class FilesWebController { @Autowired private RestTemplate restTemplate; private static final String SERVER_TRILATERAL_9400 = "http://SERVER-TRILATERAL-9400"; /** * 文件上传 * [id] * @return {@link Result} * @throws * @author 李庆伟 * @date 2021/7/29 9:56 */ @PostMapping("upFile") @ApiOperation(value = "文件上传", notes = "文件上传", produces = "application/json") @ApiResponses({ @ApiResponse(code = 0, message = "id:文件id"), })//@ApiParam(required = true, value = "上传的文件") @RequestParam(value = "file" ,required = true) public Result upFile(MultipartFile file){ // 封装参数,千万不要替换为Map与HashMap,否则参数无法传递 MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<String, Object>(); paramMap.add("file",file.getResource()); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.MULTIPART_FORM_DATA); //headers.add();在请求头中设置传递信息 HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<MultiValueMap<String, Object>>(paramMap,headers); Result result = restTemplate.postForObject(SERVER_TRILATERAL_9400+"/files/upFile",httpEntity,Result.class); return result; } /** * 图片展示[跨服务调用] * [id] * @return {@link Result} * @throws * @author 李庆伟 * @date 2021/9/6 19:15 */ @GetMapping("downFileCross") public void downFileCross(@ApiParam(required = true, value = "图片id") @RequestParam String id, HttpServletResponse response){ // 封装参数,千万不要替换为Map与HashMap,否则参数无法传递 ResponseEntity<byte[]> rsp = restTemplate.getForEntity(SERVER_TRILATERAL_9400+"/files/downFileCross?id="+id,byte[].class); BufferedInputStream bis = null; if (Objects.nonNull(rsp)) { byte[] body = rsp.getBody(); if (Objects.nonNull(body)) { try { InputStream is = new ByteArrayInputStream(body); BufferedImage image = ImageIO.read(is); //判断是否是图片 1.是预览 2.下载 if(image!=null){ //打开本地文件流 //激活下载操作 response.setContentType("image/jpeg"); ImageIO.write(image, "JPEG", response.getOutputStream()); } else { log.info("文件大小==>:{}", body.length); String filename = "李庆伟.jpg";//这里应该查询出文件名称,为了方便就随便命名了 response.setContentType("application/octet-stream"); response.setHeader("Content-disposition", "attachment; filename=" + new String(filename.getBytes("utf-8"), "ISO8859-1")); bis = new BufferedInputStream(is); OutputStream os = response.getOutputStream(); byte[] buffer = new byte[2048]; int i = bis.read(buffer); while (i != -1) { os.write(buffer, 0, i); i = bis.read(buffer); } } } catch (IOException e) { e.printStackTrace(); } finally { if (bis != null) { try { bis.close(); } catch (IOException e) { e.printStackTrace(); } } } } } } }
B服务【被A调用】
控制层: /** * 文件上传 * [file, request] * @return {@link Result} * @throws * @author 李庆伟 * @date 2021/9/4 18:05 */ @PostMapping("upFile") @ApiOperation(value = "文件上传", notes = "文件上传", produces = "application/json") @ApiResponses({ @ApiResponse(code = 0, message = "id:文件id"), }) public Result upFile(@ApiParam(required = true, value = "上传的文件") @RequestParam(value = "file" ,required = true) MultipartFile file){ CClientFile cClientFile = fileService.upFile(file); return Result.success(cClientFile);//返回上传成功文件信息 }
/** * 下载和预览[支持跨服务调用] * [id] * @return {@link Result} * @throws * @author 李庆伟 * @date 2021/9/4 20:15 */ @GetMapping("downFileCross") @ApiOperation(value = "文件下载[支持跨服务调用]", notes = "文件下载[支持跨服务调用]", produces = "application/json") public ResponseEntity<byte[]> downFileCross(@ApiParam(required = true, value = "文件id") @RequestParam(value = "id" ,required = true) String id){ return fileService.downFileCross(id);//返回上传成功文件信息 }
实现类:
/** * 文件上传业务 * @return {@link String} * @throws * @author 李庆伟 * @date 2021/9/4 19:23 */ @Transactional public CClientFile upFile(MultipartFile file) { CClientFile cClientFile = FileUtil.upFile(file); if(cClientFile == null){ throw new MyException(2001,"文件为空文件"); } String id = IdWorker.makeIdWorker(); cClientFile.setId(id); cClientFile.setCreateDate(new Date()); fileMapper.insert(cClientFile); return cClientFile; }
/** * 文件下载[支持微服务] * [id] * @return {@link ResponseEntity<byte[]>} * @throws * @author 李庆伟 * @date 2021/9/7 16:40 */ public ResponseEntity<byte[]> downFileCross(String id) { CClientFile cClientFile = fileMapper.selectById(id); if(cClientFile != null){ return FileUtil.downFileCross(cClientFile); } return null; }
工具类:
import com.files.model.CClientFile; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.multipart.MultipartFile; import javax.imageio.ImageIO; import javax.servlet.http.HttpServletResponse; import java.awt.image.BufferedImage; import java.io.*; import java.text.SimpleDateFormat; import java.util.Date; import java.util.UUID; /** * @author 李庆伟 * @date 2021/9/4 18:08 */ @Slf4j public class FileUtil { private static final String rootUtl = System.getProperty("os.name").toLowerCase().startsWith("win")?"D:/file_db/":"/file_db/"; /** * 文件上传 * [file] * @return {@link String} * @throws * @author 李庆伟 * @date 2021/9/4 18:15 */ public static CClientFile upFile(MultipartFile file){ CClientFile cClientFile = new CClientFile(); //如果文件不为空 if (!file.isEmpty()) { String oldFileName = file.getOriginalFilename(); String realPath = rootUtl + new SimpleDateFormat("yyyy/MM/dd/hh/mm/ss").format(new Date())+"/"+ UUID.randomUUID().toString().replaceAll("-", ""); File f = new File(realPath); if(!f.exists()){ f.mkdirs();//如果目录不存在,创建目录 } try { file.transferTo(new File(realPath + File.separator + oldFileName));//把文件写入目标文件地址 //可以在这完成数据库路径的存储 } catch (Exception e) { e.printStackTrace(); } cClientFile.setFileName(oldFileName);//封装文件名称 cClientFile.setFileUrl(realPath + "/" + oldFileName);//封装文件路径 cClientFile.setFileSize(file.getSize());//封装文件大小 return cClientFile;//返回到成功页面 }else { return null;//返回到失败的页面 } }
/** * * 跨服务下载 * @return {@link } * @throws * @author 李庆伟 * @date 2021/9/7 16:26 */ public static ResponseEntity<byte[]> downFileCross(CClientFile cClientFile){ String path = cClientFile.getFileUrl(); HttpHeaders headers = new HttpHeaders(); ResponseEntity<byte[]> entity = null; BufferedInputStream bis; ByteArrayOutputStream bos = new ByteArrayOutputStream(); byte[] buf = new byte[10240]; try { bis = new BufferedInputStream(new FileInputStream(path)); while (true) { int len = bis.read(buf); if (len < 0) { break; } bos.write(buf, 0, len); } //将输出流转为字节数组,通过ResponseEntity<byte[]>返回 byte[] b = bos.toByteArray(); log.info("接收到的文件大小为:" + b.length); HttpStatus status = HttpStatus.OK; String fileName = cClientFile.getFileName(); headers.setContentType(MediaType.ALL.APPLICATION_OCTET_STREAM); headers.add("Content-Disposition", "attachment;filename=" + fileName); entity = new ResponseEntity<>(b, headers, status); } catch (Exception e) { e.printStackTrace(); } finally { if (bos != null) { try { bos.close(); } catch (IOException e) { e.printStackTrace(); } } } return entity; } }
文件实体类:
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.io.Serializable; import java.util.Date; /** * 文件实体 * @author 李庆伟 * @date 2021/7/19 17:00 */ @Data @TableName("c_client_file") public class CClientFile implements Serializable { private static final long serialVersionUID = 1L; @TableId private String id;//主键 @ApiModelProperty(value = "文件名称") private String fileName;//文件名称 @ApiModelProperty(value = "文件地址") private String fileUrl;//文件地址 @ApiModelProperty(value = "文件大小") private long fileSize;//文件大小 private String createUser;//创建人 private Date createDate;//创建时间 //@TableField(exist = false) }
在说明一下Result是返回的结果集,这里就不写了,之前的文章中有结果集说明
最后完。。。。。。。。。。