

手把手编写文件服务器 - 大南好南
source link: https://www.cnblogs.com/wangchuanji/p/16003997.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

手把手编写文件服务器
一、项目需求
最近做了人力资源管理相关的项目,涉及到文件的上传、下载和预览等功能,由于条件有限,只能自己手写文件服务器。
二、思路
由于用的是SpringBoot版本,这边进行相应的文件参数配置以及项目部署的服务器划分出相应静态文件区域,进行流上传,路径存储,下载和预览通过转换成Base64给前端来实现,下面就来看下代码的实现过程。
三、实现过程
1.在application.yml文件进行配置声明
#文件上传 upload: path: #临时上传目录(本地测试环境) temporary: D:/desk/up/ #正式上传目录(正式环境) formal: /home/formal/file/CV/ #正式上传目录(正式环境) formalOffer: /home/formal/file/offer/ #转化后图片保存路径(本地测试环境) imgTemp: D:/desk/up/img #转化后图片保存路径(正式环境) img: /home/formal/file/picture/CV/ #转化后图片保存路径(正式环境) imgOffer: /home/formal/file/picture/offer/ multipart: #单个文件最大内存 maxFileSize: 5MB #所有文件最大内存 maxRequestSize: 10MB
2.编写FileConfig配置类
import lombok.Data; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; /** * 功能描述: 文件上传配置类 * * @author WCJ * @date 2022/3/1 9:05 */ @Data @Configuration public class FilesConfig { /** * 单文件上传最大内存 */ @Value("${upload.multipart.maxFileSize}") private String maxFileSize; /** * 多文件上传最大内存 */ @Value("${upload.multipart.maxRequestSize}") private String maxRequestSize; /** * 文件上传临时目录 */ @Value("${upload.path.temporary}") private String temporaryPath; /** * 简历文件上传正式目录 */ @Value("${upload.path.formal}") private String formalPath; /** * 简历图片生成路径 */ @Value("${upload.path.img}") private String imgUrl; /** * offer文件上传正式目录 */ @Value("${upload.path.formalOffer}") private String offerFormalPath; /** * offer图片生成路径 */ @Value("${upload.path.imgOffer}") private String offerImgUrl; /** * 测试环境图片生成路径 */ @Value("${upload.path.imgTemp}") private String tempImgUrl; }
Tip1--这边需要注意的是,由于使用到@Value路径注入,如果配置信息是写在 application-dev.yml 里面的话,在启动项目是会出现类比dev配置文件先加载的问题,出现加载报空的问题,解决方法是把配置信息放在总配置文件 application.yml 第一时间加载出来。
3.编写对应Controller--文件上传
/** * 服务对象 */ @Resource(name = "fileBPO") private FileBPO fileBPO; /** * 文件配置对象 */ @Resource private FilesConfig filesConfig; /** * 设置文件上传大小:在配置文件中限定 * @return */ @Bean public MultipartConfigElement multipartConfigElement() { MultipartConfigFactory factory = new MultipartConfigFactory(); //单个文件最大 factory.setMaxFileSize(DataSize.parse(filesConfig.getMaxFileSize())); //设置总上传数据总大小 factory.setMaxRequestSize(DataSize.parse(filesConfig.getMaxRequestSize())); return factory.createMultipartConfig(); } /** * 仅上传简历返回文件id * @param request 文件 * @return 简历文件id * @throws IOException */ @OperLog @PostMapping("/uploadCV") @ApiOperation(value= "上传简历", notes = "仅上传简历并返回文件id\n"+ "{HttpServletRequest 流形式上传\n" + "MultipartFile文件,(仅支持 doc、png、pdf、jpeg、jpg),<=5M\n" + "}") public AjaxResponse uploadCV(HttpServletRequest request) throws IOException { AjaxResponse ajaxResponse = new AjaxResponse(); try{ MultipartHttpServletRequest mureq = (MultipartHttpServletRequest) request; Map<String, MultipartFile> files = mureq.getFileMap(); MultipartFile fileNew = files.get("file"); //文件过滤 // 文件名 String fileName = fileNew.getOriginalFilename(); // 在file文件夹中创建名为fileName的文件 assert fileName != null; int split = fileName.lastIndexOf("."); // 文件后缀,用于判断上传的文件是否是合法的 String suffix = fileName.substring(split+1,fileName.length()); if("jpg".equals(suffix) || "jpeg".equals(suffix) || "png".equals(suffix)|| "pdf".equals(suffix) || "doc".equals(suffix)) { // 正确的类型,保存文件 String fileId = fileBPO.uploadCV(fileNew, filesConfig.getFormalPath(),filesConfig.getImgUrl()); if(!StringUtils.isBlank(fileId)){ ajaxResponse.setData("data",fileId); ajaxResponse.setMsg("上传成功"); }else { throw new BusinessException("上传失败:数据库表同步失败"); } }else{ throw new BusinessException("上传失败:上传简历(仅支持 doc、png、pdf、jpeg、jpg格式)"); } }catch (Exception ex){ throw new BusinessException("上传失败:文件接收处理异常"+ex.getMessage()); } return ajaxResponse; }
Tip2--这个地方一开始传参用的是 @RequestParam("file")MultipartFile file 但是postman测试始终拿不到文件信息,出现下图报错,后面想了下:一般在前端上传文件的话,他会有专门的一个id ,然后后端根据id来确认是不是这个文件,后面我们postman是拿到这个文件了,可是没有对应的识别id,然后就是一直为空,后面我换了一个文件上传的写法:用HttpServletRequest的方式,终于拿到的流信息。
4.编写对应BPO方法及其实现类
/** * 上传文件返回文件id * @param file 文件 * @param path 原文件路径 * @param imgPath 图片路径 * @return 文件id */ String uploadCV(MultipartFile file, String path,String imgPath) throws IOException;
@Override public String uploadCV(MultipartFile file, String path,String imgPath) throws IOException { //获取当前登录人 HashMap<String,String> map = UserUtil.getAbb001AndUserId(); String userid= map.get("userid"); //时间文件夹 SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS"); String dateStr =""; try { //1、日期转字符串 Calendar calendar = Calendar.getInstance(); Date date = calendar.getTime(); dateStr = sdf.format(date); } catch (Exception e) { throw new BusinessException(e.getMessage()); } //新的文件存放路径加上新的文件名 String fileName = file.getOriginalFilename(); int split = fileName.lastIndexOf("."); // 文件名、文件后缀 String name = fileName.substring(0,split); String suffix = fileName.substring(split+1,fileName.length()); String uuId = UUID.randomUUID().toString().replace("-", ""); String newName = name+ "." + suffix; String newPath = path + userid+"/"+dateStr +"/"+uuId+"/"+newName; File file1 = new File(newPath); //判断文件目录是否存在 this.checkFile(newPath); //存储文件 file.transferTo(file1); //新建文件上传对象 AccessoryInfo accessoryInfo = new AccessoryInfo(); //TODO 将对应的文件路径、大小、格式等基本信息存储到数据库 //文件转化 ~~String png = imgPath + userid+"/"+dateStr +"/"+ uuId+"/"+name + ".png";~~ ~~String pdf = imgPath + userid+"/"+dateStr +"/"+uuId+"/"+name+ ".pdf";~~ ~~String imgSource = this.toPng(suffix,newPath,pdf,png);~~ accessoryInfo.setImgSource(imgSource); //同步添加到文件上传表 int save = 0; try{ save= accessoryInfoBPO.saveAccessoryInfo(accessoryInfo); //返回文件id return accessoryInfo.getId(); }catch (Exception e){ throw new BusinessException("AccessoryInfo表新增失败"+e.getMessage()); } }
/** * 判断文件目录是否存在 * @param path 文件路径 * @return */ public void checkFile(String path) { File file1 = new File(path); //判断文件目录是否存在 if (!file1.getParentFile().exists()) { //创建文件存放目录 //无论是几个/,都是创建一个文件夹 //mkdirs(): 创建多层目录,如:E:/upload/2019 //mkdir(): 只创建一层目录,如:E:upload //如果不加这一行不会创建新的文件夹,会报系统找不到路径 file1.getParentFile().mkdirs(); } }
5.编写对应Controller--文件下载
/** * 简历下载 * @param ccb212 简历文件id * @return 简历下载情况 */ @OperLog @GetMapping("/downFile") @ApiOperation(value= "简历下载", notes = "根据文件id返回base64\n"+ "{\"ccb212\": \"简历文件id\",\n" + "}") public AjaxResponse downFile(@RequestParam("ccb212") String ccb212) { AjaxResponse ajaxResponse = new AjaxResponse(); //根据文件id查询相应的文件存储路径 String base64 = cb02BPO.getUrlById(ccb212); if (!StringUtils.isBlank(base64)){ //转base64 File file = new File(base64); ToPngUtil toPngUtil = new ToPngUtil(); String toBase64 = toPngUtil.toBase64(file); // ajaxResponse.setData("data",toBase64); ajaxResponse.setMsg("下载成功"); } return ajaxResponse; }
/** * 将文件转化为Base64字符串 * @param file * @return Base64字符串 */ public String toBase64(File file){ InputStream in = null; byte[] data = null; try{ in = new FileInputStream(file); data = new byte[in.available()]; in.read(data); }catch (IOException e){ throw new BusinessException("文件转化为Base64字符串格式失败:"+e.getMessage()); }finally{ if (in != null) { try { in.close(); } catch (IOException e) { throw new BusinessException("文件转化为Base64字符串格式失败:"+e.getMessage()); } } } //Base64编码 BASE64Encoder encoder = new BASE64Encoder(); return "data:image/png;base64," + encoder.encode(data); }
四、尾言
看到这儿,基本的文件上传服务器功能就已经实现了,可以根据业务的需求对方法进行自适应操作,后续笔者也会持续更新相关的工具类解析,看到这里的小伙伴们,你们的点赞和评论是对笔者最大的肯定和动力~
Recommend
-
101
前言 今天我们要讲解下如何编写一个图片压缩、方向纠正插件,附带着会讲解下如何上传和预览。 为什么重点放在图片压缩和方向纠正? 相信大家在做项目过程中,经常会遇到上传图片到后端,但是由于图片过大,需要对图片压缩处理。特别在移动端,手机拍的照片普遍过于...
-
96
charts编写介绍开始快速创建一个chart模板,helmcreatemychart,执行命令后本地生成一个mychart目录.chart目录结构Chart.yaml:该chart的描述文件,包括ico地址,版本信息等vakues.yaml:给模板文件使用的变量charts:依赖其他包的charts文件requirements.yaml:依赖的char...
-
63
0×00 前言 我的TodoList增加了一项,Appium | Airtest 抖音自动评论、创意评论(所有评论/前一百评论男女占比 | 所有评论词云),记录了当时的一个想法。Appium和Airtest都可用于移动端自动化测试,Airtest是网易家的,想做评...
-
15
本文最初发布于 Renato Athaydes 的个人网站,经原作者授权由 InfoQ 中文站翻译并分享。 目前,为 HTTP API 编写自动化测试实在有点太...
-
3
Swift是世界上最好的语言! 提倡培养自动化思维处理日常工作,提高效率,时间和精力聚焦到更关键的点上。 对于具有重复性或周期性的工作可以思考使用各种自动化方式去解决,如替换App
-
7
重磅推荐:对标产品总监 手把手教你编写《评审提纲》...
-
4
手把手带你编写属于自己的 starter ...
-
3
Linux上安装文件服务器FTP 由于FTP、HTTP、Telnet等协议的数据都是使用明文进行传输的,因此从设计上就是不可靠的。人们为了满足以密文方式传输文件的需求,发明了vsftpd服务程序。vsftpd(very secure ftp daemon,非常安全的FTP守护进程)是一款...
-
4
11. 用Rust手把手编写一个wmproxy(代理,内网穿透等), 实现健康检查 项目 ++wmproxy++ gite: ht...
-
4
12. 用Rust手把手编写一个wmproxy(代理,内网穿透等), TLS的双向认证信息及token验证 项目 ++wmproxy++
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK