在springboot项目中经常会有上传和下载的需求,此文章主要讲述在springboot项目中可能应用到的文件知识!假设我们需要将一些文件保存到服务器并将其对应信息记录到数据库中,接着能够通过前端发送的请求对文件进行相应的上传、下载和删除工作。
一、本地服务器文件的上传、下载和删除
(这里说的本地服务器是指项目部署所在服务器且文件存放在与jar包同级的static的File目录下) 1.创建名为File的数据库(这里使用mysql数据库),并添加resource表,此表将记录所有文件信息,其中有主键id,文件名resource_url以及文件描述resource_desc字段。如下图:
2.在springboot中创建对应的Service层、Dao层、Controller层以及Entity层等(这里整合了mybatisplus): (1)新建resource表中对应的实体类ResourceDO以及文件传输对象ResourceDTO:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 @Data @EqualsAndHashCode(callSuper = false) @Accessors(chain = true) @TableName("resource") public class ResourceDO implements Serializable { @TableId(value = "id", type = IdType.AUTO) private Integer id; private String resourceUrl; private String resourceDesc; }
1 2 3 4 5 6 @Data public class ResourceDTO { private String resourceDesc; }
(2)建立数据操作层ResourceMapper
1 2 3 4 5 6 7 8 9 10 @Repository public interface ResourceMapper extends BaseMapper <ResourceDO>{ ResourceDO getResourceById (Integer resourceId) ; }
对应的ResourceMapper.xml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace ="com.fileexample.filedemo.mapper.ResourceMapper" > <resultMap id ="BaseResultMap" type ="com.fileexample.filedemo.entity.ResourceDO" > <id column ="id" property ="id" /> <result column ="resource_url" property ="resourceUrl" /> <result column ="resource_desc" property ="resourceDesc" /> </resultMap > <sql id ="Base_Column_List" > id, resource_url, resource_desc </sql > <select id ="getResourceById" resultMap ="BaseResultMap" > select <include refid ="Base_Column_List" /> from resource where id = #{resourceId} </select > </mapper >
(3)新建ResourceService以及其对应的实现类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 public interface ResourceService extends IService <ResourceDO>{ Integer uploadLocalResource (MultipartFile multipartFile, ResourceDTO resourceDTO) ; boolean LocalDownload (String LocalFileName, HttpServletResponse response) ; boolean LocalDelete (Integer resourceId,String LocalFileName) ; ResourceDO getResourceById (Integer resourceId) ;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 @Service @Slf4j public class ResourceServiceImpl extends ServiceImpl <ResourceMapper, ResourceDO> implements ResourceService { @Autowired private ResourceMapper resourceMapper; @Override @Transactional(rollbackFor=Exception.class) public Integer uploadLocalResource (MultipartFile multipartFile, ResourceDTO resourceDTO) { File uploadPath = null ; try { File rootPath = new File (ResourceUtils.getURL("classpath:" ).getPath()); if (!rootPath.exists()) { rootPath = new File ("" ); } uploadPath = new File (rootPath.getAbsolutePath(), "static/File" ); if (!uploadPath.exists()) { uploadPath.mkdirs(); } } catch (FileNotFoundException e) { log.info("上传路径不存在" ); return null ; } String filename = multipartFile.getOriginalFilename(); if (StringUtils.isBlank(filename)) { log.info("上传文件不合法" ); return null ; } String fileExtensionName = filename.substring(filename.lastIndexOf("." )); String fileNewName = UUID.randomUUID().toString() + fileExtensionName; try { multipartFile.transferTo(new File (uploadPath, fileNewName)); } catch (IOException e) { log.info("上传文件错误" ); return null ; } ResourceDO resourceDO = new ResourceDO (); resourceDO.setResourceUrl(fileNewName); resourceDO.setResourceDesc(resourceDTO.getResourceDesc()); if (resourceMapper.insert(resourceDO) < 1 ) { throw new PersistenceException ("插入resource表失败" ); } return resourceDO.getId(); } @Override public boolean LocalDownload (String LocalFileName, HttpServletResponse response) { response.setHeader("content-type" , "application/octet-stream" ); response.setContentType("application/octet-stream" ); try { response.setHeader("Content-Disposition" , "attachment;filename=" + java.net.URLEncoder.encode(LocalFileName, "UTF-8" )); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } byte [] buff = new byte [1024 ]; BufferedInputStream bis = null ; OutputStream os = null ; try { File uploadPath = null ; try { File rootPath = new File (ResourceUtils.getURL("classpath:" ).getPath()); uploadPath = new File (rootPath.getAbsolutePath(), "static/File" ); } catch (FileNotFoundException e) { log.info("上传路径不存在" ); return false ; } os = response.getOutputStream(); bis = new BufferedInputStream (new FileInputStream (new File (uploadPath, LocalFileName))); int i = bis.read(buff); while (i != -1 ) { os.write(buff, 0 , buff.length); os.flush(); i = bis.read(buff); } } catch (FileNotFoundException e1) { log.info("找不到指定的文件" ); }catch (IOException e) { e.printStackTrace(); } finally { if (bis != null ) { try { bis.close(); } catch (IOException e) { e.printStackTrace(); } } } return false ; } @Override public boolean LocalDelete (Integer resourceId, String LocalFileName) { File uploadPath = null ; try { File rootPath = new File (ResourceUtils.getURL("classpath:" ).getPath()); uploadPath = new File (rootPath.getAbsolutePath(), "static/File" ); } catch (FileNotFoundException e) { log.info("上传路径不存在" ); return false ; } File targetFile = new File (uploadPath, LocalFileName); try { targetFile.delete(); resourceMapper.deleteById(resourceId); return true ; } catch (Exception e) { log.info("上传文件出错" ); return false ; } } @Override public ResourceDO getResourceById (Integer resourceId) { return resourceMapper.getResourceById(resourceId); }
(4)文件控制器FileController为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 @RestController @RequestMapping("/file") public class FileController { @Autowired private ResourceService resourceService; @PostMapping("/local-single-upload") public String localSingleUpload (@RequestParam("file") MultipartFile file, ResourceDTO resourceDTO) { int resourceId=resourceService.uploadLocalResource(file, resourceDTO); return "上传单文件到本地服务器成功,此文件的id为:" + resourceId; } @PostMapping("/local-Multiple-upload") public String localMultipleUpload (@RequestParam("files") MultipartFile[] files, ResourceDTO resourceDTO) { for (MultipartFile file : files){ int resourceId=resourceService.uploadLocalResource(file, resourceDTO); System.out.println("上传到本地服务器成功的文件id为:" + resourceId); } return "上传多文件本地服务器成功" ; } @GetMapping("/local-download") public String localDownload (@RequestParam("resourceId") Integer resourceId, HttpServletResponse response) { ResourceDO resourceDO=resourceService.getResourceById(resourceId); boolean success=resourceService.LocalDownload(resourceDO.getResourceUrl(),response); if (success){ return "下载本地服务器文件成功" ; } return "下载本地服务器文件失败" ; } @GetMapping("/local-delete") public String localDelete (@RequestParam("resourceId") Integer resourceId) { ResourceDO resourceDO=resourceService.getResourceById(resourceId); boolean success=resourceService.LocalDelete(resourceId,resourceDO.getResourceUrl()); if (success){ return "删除在本地服务器的文件成功" ; } return "删除在本地服务器的文件失败" ; } }
3.测试 (1)上传单个文件: 先创建好一个文本文件:
postman测试如下:
项目根目录以及数据库有了相应的数据:
(2)上传多个文件 再创建两个文本文件:
postman测试如下:
控制台、项目根目录以及数据库有了相应的数据:
(3)下载文件: 假设要下载id为14的文件: 在浏览器中运行以下路径后id为14的文件会下载到电脑默认的下载路径下
(4)删除文件 假设要删除id为14的文件:
发现以下关于id为14的文件信息已被删除:
二、ftp服务器文件的上传、下载和删除 FTP简介: FTP 是用来传送文件的协议。使用 FTP 实现远程文件传输的同时,还可以保证数据传输的可靠性和高效性。 具体可参考https://blog.csdn.net/u013233097/article/details/89449668
1.安装vsftpd 可参考链接https://www.cnblogs.com/magic-chenyang/p/10383929.html
2.springboot需要引入对应的依赖:
1 2 3 4 5 <dependency > <groupId > commons-net</groupId > <artifactId > commons-net</artifactId > <version > 3.6</version > </dependency >
3.新建FtpUtils类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 @Component @Slf4j public class FtpUtils { private static final String ftpIp = "127.0.0.1" ; private static final int ftpPort = 21 ; private static final String ftpUser = "uftp" ; private static final String ftpPassword = "password" ; private static final String ftpPath = "File/" ; private static final String localPath = "/home/zhu/Desktop/downloads/" ; private static FTPClient getFTPClient () { FTPClient ftpClient = new FTPClient (); try { ftpClient = new FTPClient (); ftpClient.connect(ftpIp, ftpPort); ftpClient.login(ftpUser, ftpPassword); ftpClient.setControlEncoding("UTF-8" ); ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE); ftpClient.enterLocalPassiveMode(); if (!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) { log.info("未连接到FTP,用户名或密码错误" ); ftpClient.disconnect(); } else { log.info("FTP连接成功" ); } } catch (Exception e) { log.info("FTP连接错误" ); e.printStackTrace(); } return ftpClient; } public static boolean uploadFile (String fileName, MultipartFile file) throws IOException { boolean success = false ; InputStream inputStream = file.getInputStream(); FTPClient ftpClient = getFTPClient(); try { if (!ftpClient.changeWorkingDirectory(ftpPath)){ String[] dirs = ftpPath.split("/" ); for (String dir : dirs){ if (!ftpClient.changeWorkingDirectory(dir)) { if (!ftpClient.makeDirectory(dir)) { log.info("创建目录" + dir + "失败" ); return false ; }else { ftpClient.changeWorkingDirectory(dir); log.info("创建目录" + dir + "成功" ); } } } } ftpClient.setBufferSize(1024 ); ftpClient.storeFile(fileName, inputStream); inputStream.close(); ftpClient.logout(); success = true ; } catch (IOException e) { e.printStackTrace(); } finally { if (ftpClient.isConnected()) { try { ftpClient.disconnect(); } catch (IOException ioe) { } } } return success; } public static boolean downloadFile (String ftpFileName) { FTPClient ftpClient = null ; try { ftpClient = getFTPClient(); ftpClient.changeWorkingDirectory(ftpPath); File localFile = new File (localPath + ftpFileName); OutputStream outputStream = new FileOutputStream (localFile); ftpClient.retrieveFile(ftpFileName, outputStream); outputStream.close(); ftpClient.logout(); log.info("下载成功" ); return true ; } catch (FileNotFoundException e) { log.error("没有找到" + ftpFileName + "文件" ); } catch (SocketException e) { log.error("连接FTP失败" ); } catch (IOException e) { log.error("文件读取错误" ); } log.info("下载失败" ); return false ; } public static boolean deleteFile (String filename) { FTPClient ftpClient = getFTPClient(); boolean success = false ; try { ftpClient.changeWorkingDirectory(ftpPath); ftpClient.dele(filename); success = true ; } catch (Exception e) { e.printStackTrace(); } finally { if (ftpClient.isConnected()) { try { ftpClient.disconnect(); } catch (IOException ioe) { log.error("关闭FTP连接失败" ); } } } return success; } }
4.往ResourceService和ResourceServiceImpl中添加如下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 Integer uploadFtpResource (MultipartFile multipartFile, ResourceDTO resourceDTO) ; boolean ftpDownload (String ftpFileName) ;boolean ftpDelete (Integer resourceId, String ftpFileName) ;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 @Override public Integer uploadFtpResource (MultipartFile multipartFile, ResourceDTO resourceDTO) { String filename = multipartFile.getOriginalFilename(); if (StringUtils.isBlank(filename)) { log.info("上传文件不合法" ); return null ; } String fileExtensionName = filename.substring(filename.lastIndexOf("." )); String fileNewName = UUID.randomUUID().toString() + fileExtensionName; try { FtpUtils.uploadFile(fileNewName,multipartFile); } catch (IOException e) { log.info("上传文件出错" ); return null ; } ResourceDO resourceDO = new ResourceDO (); resourceDO.setResourceUrl(fileNewName); resourceDO.setResourceDesc(resourceDTO.getResourceDesc()); if (resourceMapper.insert(resourceDO) < 1 ) { throw new PersistenceException ("插入resource表失败" ); } return resourceDO.getId(); } @Override public ResourceDO getResourceById (Integer resourceId) { return resourceMapper.getResourceById(resourceId); } @Override public boolean ftpDownload (String ftpFileName) { return FtpUtils.downloadFile(ftpFileName); } @Override public boolean ftpDelete (Integer resourceId, String ftpFileName) { if (FtpUtils.deleteFile(ftpFileName)){ resourceMapper.deleteById(resourceId); return true ; }else { return false ; } }
5.添加如下代码到FileController:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 @PostMapping("/Ftp-single-upload") public String FtpSingleUpload (@RequestParam("file") MultipartFile file, ResourceDTO resourceDTO) { int resourceId=resourceService.uploadFtpResource(file,resourceDTO); return "上传单文件到FTP服务器成功,此文件的id为:" + resourceId; } @PostMapping("/Ftp-Multiple-upload") public String FtpMultipleUpload (@RequestParam("files") MultipartFile[] files, ResourceDTO resourceDTO) { for (MultipartFile file : files){ int resourceId=resourceService.uploadFtpResource(file,resourceDTO); System.out.println("上传到FTP服务器成功的文件id为:" + resourceId); } return "上传多文件FTP服务器成功" ; } @PostMapping("/ftp-download") public String ftpDownload (Integer resourceId) { ResourceDO resourceDO=resourceService.getResourceById(resourceId); boolean success=resourceService.ftpDownload(resourceDO.getResourceUrl()); if (success){ return "下载ftp服务器文件到本地成功" ; } return "下载ftp服务器文件到本地失败" ; } @PostMapping("/ftp-delete") public String ftpDelete (@RequestParam("resourceId") Integer resourceId) { ResourceDO resourceDO=resourceService.getResourceById(resourceId); boolean success=resourceService.ftpDelete(resourceId, resourceDO.getResourceUrl()); if (success){ return "删除在ftp服务器的文件成功" ; } return "删除在ftp服务器的文件失败" ; }
6.测试 (1)上传单个文件 新建一个文本文件ftpfileone:
用postman发送上传请求:
上传成功后:
(2)上传多个文件 新建ftpfiletwo和ftpfilethree文本文件:
用postman发送上传请求:
上传成功后:
(3)下载文件 假设要下载id为17的文件:
发现成功下载到桌面上的downloads文件夹下:
(4)删除文件 假设要删除id为17的文件:
发现id为17的文件已经被删除:
三、seaweedfs服务器文件的上传、下载和删除 简介:seaweedfs是一个非常优秀的由 golang 开发的分布式存储开源项目。它是用来存储文件的系统,并且与使用的语言无关,使得文件储存在云端变得非常方便。 在逻辑上Seaweedfs的几个概念:
接下来介绍如何在服务器上搭建seaweedfs(阿里云服务器上搭建): #1.安装go环境:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 (1)下载并解压go安装包 cd /usr/local wget https://storage.googleapis.com/golang/go1.14.linux-amd64.tar.gz tar -zxvf go1.14.linux-amd64.tar.gz (2)添加go环境变量 sudo vim /etc/profile #加入 export GOPATH=/usr/local/go export PATH=$GOPATH/bin:$PATH export GOROOT=/usr/local/go export GOPATH=$PATH:$GOROOT/bin #使之生效 source /etc/profile (3)查看go版本 go version
安装完go后版本号如下:
#2.安装并运行seaweedfs (1)下载并解压seaweedfs安装包
1 2 3 cd /usr/local wget https://github.com/chrislusf/seaweedfs/releases/download/1.57/linux_amd64.tar.gz tar -zxvf linux_amd64.tar.gz
(2)创建运行目录
1 2 3 4 5 6 7 8 9 10 11 12 13 14 cd /usr/local mkdir data cd data mkdir fileData #用来存放master mkdir volume #用来存放volume mkdir logs #用来存放日志 cd volume mkdir v1 mkdir v2 cd .. cd logs touch master.log #用来存放master的日志 touch v1.log #用来存放第一个volume结点的日志 touch v1.log #用来存放第二个volume结点的日志
(3)运行master
1 sudo nohup /usr/local/weed master -mdir=/usr/local/data/fileData -port=9333 -defaultReplication="001" -ip="ip地址" >>/usr/local/data/logs/master.log &
其中各参数的意思可运行以下命令查看:
1 /usr/local/weed master -h
运行后可通过运行cat /usr/local/data/logs/master.log查看运行master的日志。 (4)运行volume
1 2 3 sudo /usr/local/weed volume -dir=/usr/local/data/volume/v1 -max=5 -mserver="ip地址:9333" -port=9080 -ip="ip地址" >>/usr/local/data/logs/v1.log & sudo /usr/local/weed volume -dir=/usr/local/data/volume/v2 -max=5 -mserver="ip地址:9333" -port=9081 -ip="ip地址" >>/usr/local/data/logs/v2.log &
其中各参数的意思可运行以下命令查看:
1 /usr/local/weed volume -h
#3.测试上传文件 (1)需要请求master, 得到分配的逻辑卷和fid
1 curl http://ip地址:9333/dir/assign
得到返回结果为:
1 {"fid":"5,020dab8398","url":"ip地址:9080","publicUrl":"ip地址:9080","count":1}
(2)使用返回的url和fid上传文件
1 curl -F file=@./seafile.txt http://ip地址:9080/5,020dab8398
得到返回结果为:
1 {"name":"seafile.txt","size":16,"eTag":"8727d9d8"}
(3)访问上传的文件 可通过在浏览器上访问以下网址:
1 http://ip地址:9080/5,020dab8398
or
1 http://ip地址:9080/5,020dab8398.txt
#4.运行Filer并挂载到本地目录 (1)设置配置文件
1 2 3 4 mkdir -p /etc/seaweedfs cd /etc/seaweedfs touch filer.toml mkdir -p /usr/local/data/filer_path
接着往filer.toml文件中添加以下内容:
1 2 3 4 recursive_delete = false [leveldb2] enabled = true dir = "/usr/local/data/filer_path"
由于这里不使用mysql、redis、cassandra等来保存数据所以对应的配置我也没写在里面。 (2)启动filer
1 /usr/local/weed filer -master=ip地址:9333 -ip=ip地址 -defaultReplicaPlacement='001'&
(3)测试上传文件
1 curl -F "filename=@./seafile.txt" "http://ip地址:8888/test/"
得到返回结果为:
1 {"name":"seafile.txt","size":16,"fid":"4,015b48397e","url":"http://ip地址:9080/4,015b48397e"}
可通过输入以下网址来访问上传的文件:
1 http://ip地址:9080/4,015b48397e
or
1 http://ip地址:8888/test/seafile.txt
#5.mount挂载 (1)设置挂载目录
1 2 cd /usr/local/data mkdir mount
(2)启动挂载
1 /usr/local/weed mount -filer=ip地址:8888 -dir=/usr/local/data/mount &
可进入到/usr/local/data/mount目录查看到刚刚上传的seafile.txt文件。
#6.seaweedfs文件服务器相关文件操作整合springboot 首先增加有关的pom文件:
1 2 3 4 5 6 7 8 9 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-webflux</artifactId > </dependency > <dependency > <groupId > commons-io</groupId > <artifactId > commons-io</artifactId > <version > 2.6</version > </dependency >
注意第一个pom文件不要换成以下pom依赖,否则在注入webclient时会报No suitable default ClientHttpConnector found……的错误,可能跟springboot的父版本有关: org.springframework spring-webflux
(1)新建Seaweedfs表以及其相应的实体类SeaweedfsDO,用来存放文件信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 @Data @EqualsAndHashCode(callSuper = false) @Accessors(chain = true) @TableName("Seaweedfs") public class SeaweedfsDO implements Serializable { @TableId(value = "id", type = IdType.AUTO) private Integer id; private String fileName; private float fileSize; private String fileFid; private String fileUrl; private String fileDesc; }
(2)建立数据操作层SeaweedfsMapper:
1 2 3 4 5 6 7 8 9 10 @Repository public interface SeaweedfsMapper extends BaseMapper <SeaweedfsDO> { SeaweedfsDO getResourceById (Integer resourceId) ; }
对应的SeaweedfsMapper.xml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace ="com.fileexample.filedemo.mapper.SeaweedfsMapper" > <resultMap id ="BaseResultMap" type ="com.fileexample.filedemo.entity.SeaweedfsDO" > <id column ="id" property ="id" /> <result column ="file_name" property ="fileName" /> <result column ="file_size" property ="fileSize" /> <result column ="file_fid" property ="fileFid" /> <result column ="file_url" property ="fileUrl" /> <result column ="file_desc" property ="fileDesc" /> </resultMap > <sql id ="Base_Column_List" > id, file_name, file_size, file_fid, file_url, file_desc </sql > <select id ="getResourceById" resultMap ="BaseResultMap" > select <include refid ="Base_Column_List" /> from Seaweedfs where id = #{resourceId} </select > </mapper >
(3)新建SeaweedfsService以及其对应的实现类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 public interface SeaweedfsService extends IService <SeaweedfsDO>{ Integer uploadSeaweedfsResource (MultipartFile multipartFile, ResourceDTO resourceDTO) ; boolean downloadSeaweedfsResource (String fileName, String downloadUrl) ; boolean DeleteSeaweedfsResource (String downloadUrl,Integer resourceId) ; SeaweedfsDO getResourceById (Integer resourceId) ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 @Service @Slf4j public class SeaweedfsServiceImpl extends ServiceImpl <SeaweedfsMapper, SeaweedfsDO> implements SeaweedfsService { @Autowired private SeaweedfsMapper seaweedfsMapper; @Value("${seaweedfs.ip}") private String seaweedfsIp; @Value("${seaweedfs.port}") private int seaweedfsPort; @Value("${seaweedfs.uploadpath}") private String seaweedfsUploadPath; @Value("${seaweedfs.localPath}") private String localPath; @Override @Transactional(rollbackFor=Exception.class) public Integer uploadSeaweedfsResource (MultipartFile multipartFile, ResourceDTO resourceDTO) { String filename = multipartFile.getOriginalFilename(); if (StringUtils.isBlank(filename)) { log.info("上传文件不合法" ); return null ; } String fileExtensionName = filename.substring(filename.lastIndexOf("." )); String fileNewName = UUID.randomUUID().toString() + fileExtensionName; File file = new File (fileNewName); try { FileUtils.copyInputStreamToFile(multipartFile.getInputStream(), file); }catch (IOException ioe){ log.info("文件错误" ); } HttpHeaders headers = new HttpHeaders (); headers.setContentType(MediaType.MULTIPART_FORM_DATA); HttpEntity<FileSystemResource> entity = new HttpEntity <>(new FileSystemResource (file), headers); Mono<UploadResponse> response = WebClient.create().post().uri("http://" + seaweedfsIp + ":" + seaweedfsPort + seaweedfsUploadPath) .contentType(MediaType.MULTIPART_FORM_DATA) .body(BodyInserters.fromMultipartData("filename" , entity)).retrieve() .bodyToMono(UploadResponse.class); UploadResponse uploadResponse = response.block(); uploadResponse.setUrl("http://" + seaweedfsIp + ":" + seaweedfsPort + seaweedfsUploadPath + file.getName()); log.info("文件发送到seaweedfs服务器完成,现在开始将文件记录到数据库里" ); SeaweedfsDO seaweedfsDO = new SeaweedfsDO (); seaweedfsDO.setFileName(uploadResponse.getName()) .setFileUrl(uploadResponse.getUrl()) .setFileFid(uploadResponse.getFid()) .setFileSize(uploadResponse.getSize()) .setFileDesc(resourceDTO.getResourceDesc()); if (seaweedfsMapper.insert(seaweedfsDO) < 1 ) { throw new PersistenceException ("插入seaweedfs表失败" ); } return seaweedfsDO.getId(); } @Override public boolean downloadSeaweedfsResource (String fileName, String downloadUrl) { Mono<ClientResponse> clientResponseMono = WebClient.create().get().uri(downloadUrl) .accept(MediaType.APPLICATION_OCTET_STREAM).exchange(); ClientResponse clientResponse = clientResponseMono.block(); assert clientResponse != null ; Resource resource = clientResponse.bodyToMono(Resource.class).block(); File file = new File (localPath + fileName); assert resource != null ; try { FileUtils.copyInputStreamToFile(resource.getInputStream(), file); }catch (IOException ioe){ log.info("文件错误" ); } return true ; } @Override public boolean DeleteSeaweedfsResource (String downloadUrl,Integer resourceId) { Mono<ClientResponse> clientResponseMono = WebClient.create().delete() .uri(downloadUrl) .accept(MediaType.APPLICATION_JSON).exchange(); ClientResponse clientResponse = clientResponseMono.block(); assert clientResponse != null ; Mono<String> response = clientResponse.bodyToMono(String.class); String a= response.block(); if (StringUtils.isBlank(a)){ seaweedfsMapper.deleteById(resourceId); return true ; } return false ; } @Override public SeaweedfsDO getResourceById (Integer resourceId) { return seaweedfsMapper.getResourceById(resourceId); } }
(4)向FileController中添加相关代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 @PostMapping("/seaweedfs-upload") public String seaweedfsUpload (@RequestParam("file") MultipartFile file, ResourceDTO resourceDTO) { int resourceId=seaweedfsService.uploadSeaweedfsResource(file,resourceDTO); return "上传文件到seaweedfs服务器成功,此文件的id为:" + resourceId; } @PostMapping("/seaweedfs-download") public String seaweedfsDownload (Integer resourceId) { SeaweedfsDO seaweedfsDO=seaweedfsService.getResourceById(resourceId); boolean success = seaweedfsService.downloadSeaweedfsResource(seaweedfsDO.getFileName(),seaweedfsDO.getFileUrl()); if (success){ return "下载seaweedfs服务器文件到本地成功" ; } return "下载seaweedfs服务器文件到本地失败" ; } @PostMapping("/seaweedfs-delete") public String seaweedfsDelete (Integer resourceId) { SeaweedfsDO seaweedfsDO=seaweedfsService.getResourceById(resourceId); boolean success = seaweedfsService.DeleteSeaweedfsResource(seaweedfsDO.getFileUrl(),resourceId); if (success){ return "删除在seaweedfs服务器的文件成功" ; } return "删除在seaweedfs服务器的文件失败" ; }
(5)测试 上传文件: 新建seafileone文本文件:
postman测试上传:
成功上传后:
下载id为4的文件:
下载成功后:
删除id为4的文件:
删除成功后test目录和数据表对应的数据空了:
#有问题欢迎指正谢谢!