SpringBoot怎么使用FTP操作文件
今天小编给大家分享一下SpringBoot怎么使用FTP操作文件的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。
简介
使用 SpringBoot 配置 FTP 服务器,上传、删除、下载文件。
配置 FTP
检查是否安装 vsftpd
rpm -qa | grep vsftpd
检修是否已经安装 vsftpd 及查看版本号.
安装 vsftpd
yum -y install vsftpd
如果报错,则使用管理员权限执行
sudo yum -y install vsftpd
关闭匿名访问
关闭匿名访问后,想访问里面的文件就需要账号和密码;如果不关,就可以直接访问。
vim /etc/vsftpd/vsftpd.conf
如果提示是只读文件,那么你只需要输入命令:
sudo vim /etc/vsftpd/vsftpd.conf
如下:
# Example config file /etc/vsftpd/vsftpd.conf## The default compiled in settings are fairly paranoid. This sample file# loosens things up a bit, to make the ftp daemon more usable.# Please see vsftpd.conf.5 for all compiled in defaults.## READ THIS: This example file is NOT an exhaustive list of vsftpd options.# Please read the vsftpd.conf.5 manual page to get a full idea of vsftpd's# capabilities.## Allow anonymous FTP? (Beware - allowed by default if you comment this out).anonymous_enable=NO## Uncomment this to allow local users to log in.local_enable=YES## Uncomment this to enable any form of FTP write command.write_enable=YES## Default umask for local users is 077. You may wish to change this to 022,# if your users expect that (022 is used by most other ftpd's)local_umask=022## Uncomment this to allow the anonymous FTP user to upload files. This only# has an effect if the above global write enable is activated. Also, you will# obviously need to create a directory writable by the FTP user.# When SELinux is enforcing check for SE bool allow_ftpd_anon_write, allow_ftpd_full_access#anon_upload_enable=YES## Uncomment this if you want the anonymous FTP user to be able to create# new directories.#anon_mkdir_write_enable=YES## Activate directory messages - messages given to remote users when they# go into a certain directory.dirmessage_enable=YES## Activate logging of uploads/downloads.xferlog_enable=YES## Make sure PORT transfer connections originate from port 20 (ftp-data).connect_from_port_20=YES## If you want, you can arrange for uploaded anonymous files to be owned by# a different user. Note! Using "root" for uploaded files is not# recommended!#chown_uploads=YES#chown_username=whoever## You may override where the log file goes if you like. The default is shown# below.#xferlog_file=/var/log/xferlog## If you want, you can have your log file in standard ftpd xferlog format.# Note that the default log file location is /var/log/xferlog in this case.xferlog_std_format=YES## You may change the default value for timing out an idle session.#idle_session_timeout=600
关闭匿名访问就是将:anonymous_enable=NO
启动服务
systemctl start vsftpd.service
查看服务状态
systemctl status vsftpd.service
[root@hadoop-master ~]# systemctl status vsftpd.service● vsftpd.service - Vsftpd ftp daemon Loaded: loaded (/usr/lib/systemd/system/vsftpd.service; disabled; vendor preset: disabled) Active: active (running) since 一 2022-12-19 10:15:39 CST; 58min ago Process: 21702 ExecStart=/usr/sbin/vsftpd /etc/vsftpd/vsftpd.conf (code=exited, status=0/SUCCESS) Main PID: 21703 (vsftpd) CGroup: /system.slice/vsftpd.service └─21703 /usr/sbin/vsftpd /etc/vsftpd/vsftpd.conf12月 19 10:15:39 hadoop-master systemd[1]: Starting Vsftpd ftp daemon...12月 19 10:15:39 hadoop-master systemd[1]: Started Vsftpd ftp daemon.[root@hadoop-master ~]#
看到绿色的
active(running)
,代表着启动成功正在运行中。
添加 FTP 用户
因为在 Linux 上,root 用户是不能登陆 FTP 的。如果你输入的是 root 用户,登陆会失败的。
adduser ftpadmin
设置密码:
passwd ftpadmin
输入两次密码就 ok 了。
配置允许root用户登录
将 /etc/vsftpd/user_list
文件和 /etc/vsftpd/ftpusers
文件中的root
这一行注释掉
修改/etc/vsftpd/vsftpd.conf
,在最后一行处添加local_root=/
service vsftpd restart
这样远程就可以root用户身份登录ftp了。
文件存储地址授权
如存储地址为:app/upload/
,设置权限为:
chmod 777 /app/upload/
SpringBoot 编码
添加依赖
<dependency> <groupId>com.jcraft</groupId> <artifactId>jsch</artifactId> <version>0.1.55</version></dependency>
操作文件工具类
package com.demo.utils;import com.jcraft.jsch.*;import com.demo.dto.UploadFileDto;import lombok.extern.slf4j.Slf4j;import java.io.File;import java.io.FileOutputStream;import java.util.Properties;@Slf4jpublic class UploadFileUtils { public static boolean upload(UploadFileDto dto) throws Exception { log.info("============上传文件开始=============="); Boolean result = false; ChannelSftp sftp = null; Channel channel = null; Session sshSession = null; try { JSch jSch = new JSch(); jSch.getSession(dto.getAccount(), dto.getHost(), dto.getPort()); sshSession = jSch.getSession(dto.getAccount(), dto.getHost(), dto.getPort()); sshSession.setPassword(dto.getPasswd()); Properties sshConfig = new Properties(); sshConfig.put("StrictHostKeyChecking", "no"); sshSession.setConfig(sshConfig); sshSession.connect(); channel = sshSession.openChannel("sftp"); channel.connect(); sftp = (ChannelSftp) channel; sftp.cd(dto.getWorkingDir()); sftp.put(dto.getInputStream(), dto.getFileName()); result = true; log.info("============上传文件结束=============="); } catch (JSchException e) { result = false; log.error("=====上传文件异常:{}", e.getMessage()); e.printStackTrace(); } finally { closeChannel(sftp); closeChannel(channel); closeSession(sshSession); } return result; } public static boolean delete(UploadFileDto dto) throws Exception { log.info("============删除文件开始=============="); Boolean result = false; ChannelSftp sftp = null; Channel channel = null; Session sshSession = null; try { JSch jSch = new JSch(); jSch.getSession(dto.getAccount(), dto.getHost(), dto.getPort()); sshSession = jSch.getSession(dto.getAccount(), dto.getHost(), dto.getPort()); sshSession.setPassword(dto.getPasswd()); Properties sshConfig = new Properties(); sshConfig.put("StrictHostKeyChecking", "no"); sshSession.setConfig(sshConfig); sshSession.connect(); channel = sshSession.openChannel("sftp"); channel.connect(); sftp = (ChannelSftp) channel; sftp.cd(dto.getWorkingDir()); sftp.rm(dto.getFileName()); result = true; log.info("============删除文件结束=============="); } catch (JSchException e) { result = false; log.error("=====删除文件异常:{}", e.getMessage()); e.printStackTrace(); } finally { closeChannel(sftp); closeChannel(channel); closeSession(sshSession); } return result; } public static boolean download(UploadFileDto dto) throws Exception { log.info("============下载文件开始=============="); Boolean result = false; ChannelSftp sftp = null; Channel channel = null; Session sshSession = null; try { JSch jSch = new JSch(); jSch.getSession(dto.getAccount(), dto.getHost(), dto.getPort()); sshSession = jSch.getSession(dto.getAccount(), dto.getHost(), dto.getPort()); sshSession.setPassword(dto.getPasswd()); Properties sshConfig = new Properties(); sshConfig.put("StrictHostKeyChecking", "no"); sshSession.setConfig(sshConfig); sshSession.connect(); channel = sshSession.openChannel("sftp"); channel.connect(); sftp = (ChannelSftp) channel; sftp.cd(dto.getWorkingDir()); sftp.get(dto.getFileName(), new FileOutputStream(new File(dto.getDownloadPath()))); sftp.disconnect(); sftp.getSession().disconnect(); result = true; log.info("============下载文件结束=============="); } catch (JSchException e) { result = false; log.error("=====下载文件异常:{}", e.getMessage()); e.printStackTrace(); } finally { closeChannel(sftp); closeChannel(channel); closeSession(sshSession); } return result; } private static void closeChannel(Channel channel) { if (channel != null) { if (channel.isConnected()) { channel.disconnect(); } } } private static void closeSession(Session session) { if (session != null) { if (session.isConnected()) { session.disconnect(); } } }}
UploadFileDto.java
package com.demo.dto;import io.swagger.annotations.ApiModel;import io.swagger.annotations.ApiModelProperty;import lombok.AllArgsConstructor;import lombok.Builder;import lombok.Data;import lombok.NoArgsConstructor;import java.io.InputStream;@Data@AllArgsConstructor@NoArgsConstructor@Builder@ApiModel(value = "上传文件Dto")public class UploadFileDto { @ApiModelProperty(value = " ftp 服务器ip地址") private String host; @ApiModelProperty(value = " ftp 服务器port,默认是21") private Integer port; @ApiModelProperty(value = " ftp 服务器用户名") private String account; @ApiModelProperty(value = " ftp 服务器密码") private String passwd; @ApiModelProperty(value = " ftp 服务器存储图片的绝对路径") private String workingDir; @ApiModelProperty(value = "上传到ftp 服务器文件名") private String fileName; @ApiModelProperty(value = " 文件流") private InputStream inputStream; @ApiModelProperty(value = " 下载文件的路径") private String downloadPath;}
UploadVo.java
package com.demo.vo;import io.swagger.annotations.ApiModel;import io.swagger.annotations.ApiModelProperty;import lombok.AllArgsConstructor;import lombok.Builder;import lombok.Data;import lombok.NoArgsConstructor;@Data@AllArgsConstructor@NoArgsConstructor@Builder@ApiModel(value = "文件VO")public class UploadVo { @ApiModelProperty(value = "原始文件名称") private String oldName; @ApiModelProperty(value = "新文件名称") private String newName; @ApiModelProperty(value = "访问路径") private String path;}
UploadController
package com.demo.controller;import com.demo.vo.UploadVo;import com.demo.service.UploadService;import io.swagger.annotations.Api;import io.swagger.annotations.ApiOperation;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.*;import org.springframework.web.multipart.MultipartFile;@Slf4j@RestController@RequestMapping("/upload")@Api(value = "upload", tags = "上传文件")public class UploadController { @Autowired private UploadService uploadService; @ApiOperation(value = "上传图片", notes = "上传图片") @PostMapping("/uploadImage") public UploadVo uploadImage(@RequestParam("file") MultipartFile file) { return uploadService.uploadImage(file); } @ApiOperation(value = "删除文件", notes = "删除文件") @GetMapping("/delFile") public Boolean delFile(String fileName) { return uploadService.delFile(fileName); } @ApiOperation(value = "下载文件", notes = "下载文件") @GetMapping("/downloadFile") public Boolean downloadFile(String fileName, String downloadPath) { return uploadService.downloadFile(fileName, downloadPath); }}
UploadService
package com.demo.service;import com.demo.vo.UploadVo;import org.springframework.web.multipart.MultipartFile;public interface UploadService { UploadVo uploadImage(MultipartFile file); Boolean delFile(String fileName); Boolean downloadFile(String fileName, String downloadPath);}
UploadServiceImpl
package com.demo.service.impl;import com.demo.dto.UploadFileDto;import com.demo.vo.UploadVo;import com.demo.config.FtpConfig;import com.demo.service.UploadService;import com.demo.utils.UUIDUtils;import com.demo.utils.UploadFileUtils;import com.demo.exception.BusinessException;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import org.springframework.web.multipart.MultipartFile;import java.time.LocalDate;import java.time.format.DateTimeFormatter;import java.util.Objects;@Slf4j@Servicepublic class UploadServiceImpl implements UploadService { @Autowired private FtpConfig ftpConfig; @Override public UploadVo uploadImage(MultipartFile file) { log.info("=======上传图片开始,图片名称:{}", file.getOriginalFilename()); try { // 1. 取原始文件名 String oldName = file.getOriginalFilename(); // 2. ftp 服务器的文件名 String newName = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")) + UUIDUtils.getUUID(10) + oldName.substring(oldName.lastIndexOf(".")); // 3.上传图片 Boolean result = UploadFileUtils.upload( UploadFileDto.builder() .host(ftpConfig.host) .port(ftpConfig.post) .account(ftpConfig.username) .passwd(ftpConfig.password) .workingDir(ftpConfig.basePath) .fileName(newName) .inputStream(file.getInputStream()) .build() ); // 4.返回结果 if (!result) { throw new BusinessException("上传图片失败!"); } log.info("=======上传图片结束,新图片名称:{}", newName); return UploadVo.builder() .oldName(oldName) .newName(newName) .path(ftpConfig.imageBaseUrl + "/" + newName) .build(); } catch (Exception e) { log.error("=======上传图片异常,异常信息:{}", e.getMessage()); e.printStackTrace(); } return null; } @Override public Boolean delFile(String fileName) { if (Objects.isNull(fileName)) { throw new BusinessException("文件名称为空,请核实!"); } try { Boolean result = UploadFileUtils.delete( UploadFileDto.builder() .host(ftpConfig.host) .port(ftpConfig.post) .account(ftpConfig.username) .passwd(ftpConfig.password) .workingDir(ftpConfig.basePath) .fileName(fileName) .build() ); return result; } catch (Exception e) { log.error("=======删除文件异常,异常信息:{}", e.getMessage()); e.printStackTrace(); } return null; } @Override public Boolean downloadFile(String fileName, String downloadPath) { if (Objects.isNull(fileName) || Objects.isNull(downloadPath)) { throw new BusinessException("文件名称或下载路径为空,请核实!"); } try { Boolean result = UploadFileUtils.download( UploadFileDto.builder() .host(ftpConfig.host) .port(ftpConfig.post) .account(ftpConfig.username) .passwd(ftpConfig.password) .workingDir(ftpConfig.basePath) .fileName(fileName) .downloadPath(downloadPath) .build() ); return result; } catch (Exception e) { log.error("=======下载文件异常,异常信息:{}", e.getMessage()); e.printStackTrace(); } return null; }}
FtpConfig
package com.demo.config;import org.springframework.beans.factory.annotation.Value;import org.springframework.stereotype.Component;@Componentpublic class FtpConfig { // ftp 服务器ip地址 @Value("${ftp.host}") public String host; // ftp 服务器port,默认是21 @Value("${ftp.post}") public Integer post; // ftp 服务器用户名 @Value("${ftp.username}") public String username; // ftp 服务器密码 @Value("${ftp.password}") public String password; // ftp 服务器存储图片的绝对路径 @Value("${ftp.base-path}") public String basePath; // ftp 服务器外网访问图片路径 @Value("${ftp.image-base-url}") public String imageBaseUrl;}
application.yml
# ftpftp: host: 127.0.0.1 post: 22 username: ftpadmin password: ftpadmin base-path: /app/upload/images image-base-url: http://127.0.0.1:8080/images
配置 Nginx
server { listen 8080; server_name localhost; location /images/ { root /app/upload/; autoindex on; }}
以上就是“SpringBoot怎么使用FTP操作文件”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注编程网行业资讯频道。
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341