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.conf 12月 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; /** * @ClassName: UploadFileUtils.java * @Description: 上傳文件 * @Author: tanyp * @Date: 2022/12/19 10:38 **/ @Slf4j public class UploadFileUtils { /** * @MonthName: upload * @Description: 上傳文件 * @Author: tanyp * @Date: 2022/12/19 10:38 * @Param: [dto] * @return: boolean **/ 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; } /** * @MonthName: delete * @Description: 刪除文件 * @Author: tanyp * @Date: 2022/12/19 10:38 * @Param: [dto] * @return: boolean **/ 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; } /** * @MonthName: download * @Description: 下載文件 * @Author: tanyp * @Date: 2022/12/19 10:38 * @Param: [dto] * @return: boolean **/ 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; /** * @ClassName: UploadFileDto.java * @ClassPath: com.demo.dto.UploadFileDto.java * @Description: 上傳文件 * @Author: tanyp * @Date: 2022/12/19 10:38 **/ @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; /** * @ClassName: UploadVo.java * @ClassPath: com.demo.vo.UploadVo.java * @Description: 文件VO * @Author: tanyp * @Date: 2022/12/19 15:18 **/ @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; /** * @ClassName: UploadController.java * @ClassPath: com.demo.controller.UploadController.java * @Description: 上傳文件 * @Author: tanyp * @Date: 2022/12/19 15:18 **/ @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; /** * @ClassName: UploadService.java * @ClassPath: com.demo.service.UploadService.java * @Description:上傳文件 * @Author: tanyp * @Date: 2022/12/19 15:18 **/ 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; /** * @ClassName: UploadServiceImpl.java * @ClassPath: com.demo.service.impl.UploadServiceImpl.java * @Description: 上傳文件 * @Author: tanyp * @Date: 2022/12/19 15:18 **/ @Slf4j @Service public 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; /** * @ClassName: FtpConfig.java * @ClassPath: com.demo.config.FtpConfig.java * @Description: FTP配置 * @Author: tanyp * @Date: 2022/12/19 22:28 **/ @Component public 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
# ftp ftp: 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 操作文件整合完成。
到此這篇關於SpringBoot 使用 FTP 操作文件的文章就介紹到這瞭,更多相關SpringBoot FTP 操作文件內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- springboot2.1.3配置sftp自定義sftp連接池的詳細過程
- Java使用Sftp和Ftp實現對文件的上傳和下載
- Linux雲服務器搭建SFTP服務器圖片服務器的操作
- JSch教程使用sftp協議實現服務器文件載操作
- Java實現FTP文件上傳