基于SFTP的文件上传下载服务
来源:互联网 发布:论文查重率软件 编辑:程序博客网 时间:2024/05/17 08:49
文件上传/下载服务是每个系统都离不开的,最近写了一个简单、通用、好用的文件上传/下载的服务。这里我们使用JSch来实现文件的上传和下载,开发框架采用的是SpringBoot+Swagger。
首先我们建立一个SFTP的工具类用来对服务器上的文件进行操作。
package org.jack.util;import com.jcraft.jsch.ChannelSftp;import com.jcraft.jsch.JSch;import com.jcraft.jsch.JSchException;import com.jcraft.jsch.Session;import com.jcraft.jsch.SftpATTRS;import com.jcraft.jsch.SftpException;import org.apache.log4j.Logger;import java.io.InputStream;import java.io.OutputStream;import java.util.Properties;/** * @author jack */public class SFTPUtil { private static final Logger logger = Logger.getLogger(SFTPUtil.class); /** * 上传文件 * * @param dataSource 连接信息 * @param directory 文件目录 * @param fileName 文件名 * @param inputStream 输入流 */ public static void upload(DataSource dataSource, String directory, String fileName, InputStream inputStream) throws SftpException, JSchException { Session session = null; ChannelSftp sftp = null; try { session = connect(dataSource); sftp = (ChannelSftp) session.openChannel("sftp"); sftp.connect(); logger.info("Channel opened."); put(sftp, directory, fileName, inputStream); } catch (SftpException sftpException) { logger.error("上传文件失败", sftpException); throw sftpException; } catch (JSchException jSchException) { logger.error("上传文件失败", jSchException); throw jSchException; } finally { disconnect(sftp); disconnect(session); } } /** * 下载文件 * * @param dataSource 连接信息 * @param directory 文件目录 * @param fileName 文件名 * @param outputStream 输出流 */ public static void download(DataSource dataSource, String directory, String fileName, OutputStream outputStream) throws SftpException, JSchException { Session session = null; ChannelSftp sftp = null; try { session = connect(dataSource); sftp = (ChannelSftp) session.openChannel("sftp"); sftp.connect(); logger.info("Channel opened."); get(sftp, directory, fileName, outputStream); } catch (SftpException sftpException) { logger.error("下载文件失败", sftpException); throw sftpException; } catch (JSchException jSchException) { logger.error("下载文件失败", jSchException); throw jSchException; } finally { disconnect(sftp); disconnect(session); } } /** * 删除文件 * * @param dataSource 连接信息 * @param directory 文件目录 * @param fileName 文件名 */ public static void delete(DataSource dataSource, String directory, String fileName) throws SftpException, JSchException { Session session = null; ChannelSftp sftp = null; try { session = connect(dataSource); sftp = (ChannelSftp) session.openChannel("sftp"); sftp.connect(); logger.info("Channel opened."); rm(sftp, directory, fileName); } catch (SftpException sftpException) { logger.error("删除文件失败", sftpException); throw sftpException; } catch (JSchException jSchException) { logger.error("删除文件失败", jSchException); throw jSchException; } finally { disconnect(sftp); disconnect(session); } } /* 连接Session */ private static Session connect(DataSource dataSource) throws JSchException { JSch jSch = new JSch(); Session session = jSch.getSession(dataSource.getUsername(), dataSource.getHost(), dataSource.getPort()); logger.info("Session created."); session.setPassword(dataSource.getPassword()); Properties config = new Properties(); config.put("StrictHostKeyChecking", "no"); session.setConfig(config); session.setTimeout(300_000); session.connect(); logger.info("Session connected."); return session; } /* 关闭Session */ private static void disconnect(Session session) { if (session != null && session.isConnected()) { session.disconnect(); logger.info("session closed."); } } /* 关闭sftp通道 */ private static void disconnect(ChannelSftp sftp) { if (sftp != null && sftp.isConnected()) { sftp.disconnect(); logger.info("sftp closed."); } } /* 上传文件 */ private static void put(ChannelSftp sftp, String directory, String fileName, InputStream inputStream) throws SftpException { try {// 切换目录 sftp.cd(directory); logger.info("run cd directory."); } catch (SftpException e) { try { mkdir(sftp, directory); sftp.cd(directory); logger.info("run mkdir directory."); logger.info("run cd directory."); } catch (SftpException sftpException) { logger.error("上传文件失败", sftpException); throw sftpException; } } try { sftp.put(inputStream, fileName); logger.info("run put file."); } catch (SftpException sftpException) { logger.error("上传文件失败", sftpException); throw sftpException; } } /* 下载文件 */ private static void get(ChannelSftp sftp, String directory, String fileName, OutputStream outputStream) throws SftpException { try { sftp.cd(directory); logger.info("run cd directory."); sftp.get(fileName, outputStream); logger.info("run get file."); } catch (SftpException sftpException) { logger.error("下载文件失败", sftpException); throw sftpException; } } /* 删除文件 */ private static void rm(ChannelSftp sftp, String directory, String fileName) throws SftpException { try { sftp.cd(directory); logger.info("run cd directory."); sftp.rm(fileName); logger.info("run rm file."); } catch (SftpException sftpException) { logger.error("删除文件失败", sftpException); throw sftpException; } } private static void mkdir(ChannelSftp sftp, String directory) throws SftpException { try { if (isDirExist(sftp, directory)) { return; } String pathArray[] = directory.split("/"); StringBuffer filePath = new StringBuffer("/"); for (String path : pathArray) { if (path.equals("")) { continue; } filePath.append(path + "/"); if (!isDirExist(sftp, filePath.toString())) { sftp.mkdir(filePath.toString()); } } } catch (SftpException sftpException) { throw sftpException; } } private static boolean isDirExist(ChannelSftp sftp, String directory) { boolean isDirExistFlag = false; try { SftpATTRS sftpATTRS = sftp.lstat(directory); isDirExistFlag = true; return sftpATTRS.isDir(); } catch (Exception e) { if (e.getMessage().toLowerCase().equals("no such file")) { isDirExistFlag = false; } } return isDirExistFlag; } public static class DataSource { private String host; private int port; private String username; private String password; public DataSource(String host, int port, String username, String password) { this.host = host; this.port = port; this.username = username; this.password = password; } public String getHost() { return host; } public void setHost(String host) { this.host = host; } public int getPort() { return port; } public void setPort(int port) { this.port = port; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }}
然后,我们定义一个业务类,对文件管理的服务进行信息更深层次的封装,以便系统的其他地方能够更简便的使用它。
package org.jack.service;import org.jack.common.CustomerException;import org.jack.common.HttpStatus;import com.eastone.lease.util.SFTPUtil;import com.jcraft.jsch.JSchException;import com.jcraft.jsch.SftpException;import org.springframework.beans.factory.annotation.Value;import org.springframework.stereotype.Service;import java.io.InputStream;import java.io.OutputStream;import java.util.UUID;/** * @author jack */@Servicepublic class FileService { @Value("${sftp.host}") public String host; @Value("${sftp.port}") public int port; @Value("${sftp.username}") public String username; @Value("${sftp.password}") public String password; /** * 上传文件 */ public String upload(String directory, String fileName, InputStream inputStream) { SFTPUtil.DataSource dataSource = new SFTPUtil.DataSource(host, port, username, password); String[] fileNameArray = fileName.split("\\."); String suffixName = fileNameArray[fileNameArray.length - 1]; fileName = UUID.randomUUID().toString().replaceAll("-", "") + "." + suffixName; try { SFTPUtil.upload(dataSource, directory, fileName, inputStream); } catch (SftpException e) { throw new CustomerException(HttpStatus.BAD); } catch (JSchException e) { throw new CustomerException(HttpStatus.BAD); } return fileName; } /** * 下载文件 */ public void download(String directory, String fileName, OutputStream outputStream) { SFTPUtil.DataSource dataSource = new SFTPUtil.DataSource(host, port, username, password); try { SFTPUtil.download(dataSource, directory, fileName, outputStream); } catch (SftpException e) { throw new CustomerException(HttpStatus.BAD); } catch (JSchException e) { throw new CustomerException(HttpStatus.BAD); } }}最后,我们对外提供一个REST风格的API。
package org.jack.controller.sys;import org.jack.common.JsonMessage;import org.jack.service.FileService;import io.swagger.annotations.Api;import io.swagger.annotations.ApiOperation;import io.swagger.annotations.ApiParam;import io.swagger.annotations.ApiResponse;import io.swagger.annotations.ApiResponses;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Value;import org.springframework.http.HttpStatus;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.RestController;import org.springframework.web.multipart.MultipartFile;import javax.servlet.http.HttpServletResponse;import java.io.IOException;import java.io.InputStream;import java.util.HashMap;import java.util.Map;/** * @author jack */@RestController@RequestMapping("/api/file")@Api(tags = "file", description = "文件API")public class FileController { @Value("${sftp.path}") public String directoryPrefix; private final static Map<String, String> directoryMap = new HashMap<>(); static { directoryMap.put("license", "license"); directoryMap.put("parking", "parking"); } @Autowired private HttpServletResponse response; @Autowired private FileService fileService; @RequestMapping(value = "/{directory}", method = RequestMethod.POST) @ApiOperation("上传文件") @ApiResponses({ @ApiResponse(code = 200, response = String.class, message = "文件路径"), }) public JsonMessage upload(@ApiParam(value = "目录", required = true) @PathVariable(value = "directory") String directory, @ApiParam(value = "文件", allowMultiple = true, required = true) @RequestParam MultipartFile file) throws IOException { if (!directoryMap.containsKey(directory)) { return JsonMessage.failed("文件上传失败"); } String fileName = file.getOriginalFilename(); System.out.println("文件名:" + fileName); InputStream inputStream = file.getInputStream(); fileName = directoryMap.get(directory) + "/" + fileService.upload(directoryPrefix + directoryMap.get(directory), fileName, inputStream); return JsonMessage.successed(fileName, "文件上传成功"); } @RequestMapping(value = "/{directory}/{fileName}.{suffix}", method = RequestMethod.GET) @ApiOperation("获取文件") @ApiResponses({ @ApiResponse(code = 200, response = String.class, message = "下载成功"), }) public void download(@ApiParam(value = "目录", required = true) @PathVariable(value = "directory") String directory, @ApiParam(value = "文件名", required = true) @PathVariable(value = "fileName") String fileName, @ApiParam(value = "后缀", required = true) @PathVariable(value = "suffix") String suffix) { try { fileService.download(directoryPrefix + directory, fileName + "." + suffix, response.getOutputStream()); } catch (Exception e) { response.setStatus(HttpStatus.NOT_FOUND.value()); } }}
总结:
代码比较简洁,结构比较清晰,没有多余的功能,但是也没有提供比较高级的特性。
阅读全文
0 0
- 基于SFTP的文件上传下载服务
- SFTP上传下载文件
- sftp文件上传下载
- SFTP之上传下载<单个>文件
- jsch实现sftp服务器的文件时上传下载
- 基于struts2的文件上传下载
- Xshell 的上传下载操作 (sftp)
- jsch java实现sftp文件上传下载
- XShell 4使用sftp上传下载文件命令
- XShell 4使用sftp上传下载文件命令
- XShell 4使用sftp上传下载文件命令
- java 通过sftp服务器上传下载删除文件
- JSch____Java实现SFTP文件上传下载…
- Python + Paramiko实现sftp文件上传下载
- python paramiko模块实现sftp上传下载文件
- Xshell5下利用sftp上传下载传输文件
- Python paramiko SFTP协议上传下载文件
- Xshell5下利用sftp上传下载传输文件
- 关于Tomact的User library与WEB-INF/lib的关系
- 关于6.0 webview加载不出图片的问题
- Linux下is not in the sudoers file解决方法
- 区块链入门(1):搭建(Ubuntu系统)Truffle v3.2.1 开发和测试环境
- boolean值在本地的存储
- 基于SFTP的文件上传下载服务
- KMP模板
- sklearn
- 面向对象
- stk 入门
- HK 2016(Colourful Graph-构造)
- iOS设置具体页面横屏或者是竖屏
- Dubbo服务启动依赖检查
- H5语义化标签笔记库