基于SFTP的文件上传下载服务
2017-10-24 17:27
441 查看
文件上传/下载服务是每个系统都离不开的,最近写了一个简单、通用、好用的文件上传/下载的服务。这里我们使用JSch来实现文件的上传和下载,开发框架采用的是SpringBoot+Swagger。
首先我们建立一个SFTP的工具类用来对服务器上的文件进行操作。
然后,我们定义一个业务类,对文件管理的服务进行信息更深层次的封装,以便系统的其他地方能够更简便的使用它。
总结:
代码比较简洁,结构比较清晰,没有多余的功能,但是也没有提供比较高级的特性。
首先我们建立一个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 pass 4000 word; 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 */ @Service public 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()); } } }
总结:
代码比较简洁,结构比较清晰,没有多余的功能,但是也没有提供比较高级的特性。
相关文章推荐
- 基于sftp来上传和下载文件
- 利用shell脚本从SFTP服务下载上传文件
- 基于Spring Mvc实现的Excel文件上传下载
- 详解基于jsp的文件的上传下载
- SFTP文件上传和下载
- 基于struts2--实现文件上传下载
- 在linux中使用rz,sz进行文件的上传和下载,用来代替SRT的sftp功能
- sftp协议下如何上传和下载文件
- struts2学习笔记(六)文件上传与下载(下)基于Struts2的文件上传与下载
- Ubuntu下通过sftp远程登录linux系统,并实现上传、下载文件
- Python3的SFTP文件上传下载
- Ubuntu下通过sftp远程登录linux系统,并实现上传、下载文件
- JSch:纯JAVA实现SFTP文件上传和下载
- 利用WCF实现上传下载文件服务
- XShell 4使用sftp上传下载文件命令
- 用C#连接SFTP服务器并进行上传下载文件
- 【WCF】利用WCF实现上传下载文件服务
- JAVA SFTP文件上传、下载及批量下载
- 如何基于OSS和MTS,快速搭建音视频文件上传服务?