注意:本文只适合小文本文件的上传下载,因为post请求是有大小限制的。默认大小是2m,虽然具体数值可以调节,但不适合做大文件的传输

最近公司有这么个需求:以后所有的项目开发中需要使用ftp服务器的地方都不能直接操作ftp服务器,而是通过调用一个统一的接口去操作文件的上传下载等功能。

其实就是针对ftp服务器封装一个项目,所有的针对ftp的操作都通过这个项目来实现。

技术点:接口调用必然存在各种参数、错误信息、成功信息等。那么我们的文件要通过什么形式放到参数中在网络传递呢?

文件可以转换成字节流在网络中传输没毛病,但是转换成二进制流之后放到我们封装的对象中再次序列化在网络中传输就有问题了。

所以关键是将我们的文件以何种数据结构封装在我们的参数对象中在网络里传输。答案是 字节数组;

目录结构:

入参对象: Vsftpd

  1. package com.ch.vsftpd.common.pojo;
  2.  
  3. /**
  4. * @Auther: 011336
  5. * @Date: 2019/4/24 11:04
  6. */
  7. public class Vsftpd {
  8. /**
  9. * 请求类型[必填]
  10. * upload: 上传 文件已存在上传失败
  11. * replace:上传 文件已存在则覆盖
  12. * download: 下载
  13. * display: 查看文件列表
  14. * delete: 删除文件
  15. */
  16. private String optionType;
  17. /**
  18. * 请求者在接口管理系统中维护的项目编码[必填]
  19. */
  20. private String projectCode;
  21. /**
  22. * 上传/下载 文件名[非必填]
  23. */
  24. private String fileName;
  25. /**
  26. * 上传/下载 文件的字节数组[非必填]
  27. */
  28. private byte[] byteArry;
  29.  
  30. ...
  31. }

返回对象: VsftpResult

  1. package com.ch.vsftpd.common.pojo;
  2.  
  3. import java.util.List;
  4.  
  5. /**
  6. * @Auther: 011336
  7. * @Date: 2019/4/24 11:03
  8. */
  9. public class VsftpResult {
  10.  
  11. private boolean status;
  12.  
  13. private byte[] byteArry;
  14.  
  15. private String[] fileNames;
  16.  
  17. private List<ErrorInfo> errors;
  18.  
  19. }

错误信息: ErrorInfo

  1. package com.ch.vsftpd.common.pojo;
  2.  
  3. /**
  4. * @Auther: 011336
  5. * @Date: 2019/3/28 11:32
  6. */
  7. public class ErrorInfo {
  8.  
  9. private String errorCode;
  10.  
  11. private String errorMsg;
  12.  
  13. public ErrorInfo() {
  14. }
  15.  
  16. public ErrorInfo(String errorCode) {
  17. this.errorCode = errorCode;
  18. }
  19.  
  20. public ErrorInfo(String errorCode, String errorMsg) {
  21. this.errorCode = errorCode;
  22. this.errorMsg = errorMsg;
  23. }
  24. }

对外提供接口: FtpController

  1. /**
  2. * ftp服务,对外提供统一接口地址,通过控制传递的参数实现 上传、覆盖上传、获取文件列表和下载4个功能
  3. * 具体参数参考【Vsftpd.java, FtpConstants】
  4. * @before AuthorityInterceptor.java 拦截器做权限校验
  5. * @Auther: 011336
  6. * @Date: 2019/4/24 11:21
  7. */
  8. @Controller
  9. @RequestMapping("/vsftpdService")
  10. public class ftpController {
  11.  
  12. private static Logger LOGGER = LoggerFactory.getLogger(ftpController.class);
  13.  
  14. @ResponseBody
  15. @RequestMapping(path = "/vsftpd", method = RequestMethod.POST)
  16. public VsftpResult getAuthInfo(@RequestBody Vsftpd vsftpd){
  17. LOGGER.info("ftpController.getAuthInfo start");
  18. IFtpUploadStrategy strategy = null;
  19. List<ErrorInfo> errors = new ArrayList<>();
  20. VsftpResult result = new VsftpResult();
  21. //第一步校验参数是否合法
  22. if (StringUtils.isEmpty(vsftpd.getOptionType())) {
  23. ErrorInfo errorInfo = new ErrorInfo("PARAMETER.FAIL","调用参数[type]不能为空!");
  24. errors.add(errorInfo);
  25. }
  26. if (StringUtils.isEmpty(vsftpd.getProjectCode())) {
  27. ErrorInfo errorInfo = new ErrorInfo("PARAMETER.FAIL","参数[projectCode]不能为空!");
  28. errors.add(errorInfo);
  29. }
  30. //根据请求类型使用不同策略
  31. if(FtpConstants.UP_LOAD.equals(vsftpd.getOptionType())){
  32. strategy = new FtpUploadStrategy();
  33. }else if(FtpConstants.REPLACE.equals(vsftpd.getOptionType())){
  34. strategy = new FtpUploadStrategy();
  35. }else if(FtpConstants.DOWAN_LOAD.equals(vsftpd.getOptionType())){
  36. strategy = new FtpDownLoadStrategy();
  37. }else if(FtpConstants.DISPLAY.equals(vsftpd.getOptionType())){
  38. strategy = new FtpDisplayStrategy();
  39. }else if(FtpConstants.DELETE.equals(vsftpd.getOptionType())){
  40. strategy = new FtpDeleteStrategy();
  41. }else {
  42. ErrorInfo errorInfo = new ErrorInfo("PARAMETER.FAIL","调用参数[type]错误!");
  43. errors.add(errorInfo);
  44. }
  45. if (CollectionUtils.isEmpty(errors)) {
  46. result = strategy.vsftpMethod(vsftpd);
  47. }else{
  48. result.setStatus(false);
  49. result.setErrors(errors);
  50. }
  51. return result;
  52. }
  53. }

四种策略:

文件上传: FtpUploadStrategy

  1. /**
  2. * 文件上传
  3. * 通过参数vsftpd.getOptionType()分为普通上传 和 覆盖上传两种
  4. * 第一种若文件已存在则返回错误信息提示文件已存在
  5. * 第二种则直接覆盖
  6. * @Auther: 011336
  7. * @Date: 2019/4/24 10:59
  8. */
  9. public class FtpUploadStrategy implements IFtpUploadStrategy {
  10.  
  11. private static Logger LOGGER = LoggerFactory.getLogger(FtpUploadStrategy.class);
  12.  
  13. @Override
  14. public VsftpResult vsftpMethod(Vsftpd vsftpd){
  15. LOGGER.info("FtpUploadStrategy.vsftpMethod start");
  16. VsftpResult result = new VsftpResult();
  17. List<ErrorInfo> errors = new ArrayList<>();
  18. if (StringUtils.isEmpty(vsftpd.getFileName())) {
  19. ErrorInfo errorInfo = new ErrorInfo("PARAMETER.FAIL","参数[fileName]不能为空!");
  20. errors.add(errorInfo);
  21. }
  22. if (vsftpd.getByteArry()==null) {
  23. ErrorInfo errorInfo = new ErrorInfo("PARAMETER.FAIL","参数[byteArry]不能为空!");
  24. errors.add(errorInfo);
  25. }
  26. //当不强制上传的时候 文件若已存在则上传失败
  27. boolean flag = false;
  28. try {
  29. if(FtpConstants.UP_LOAD.equals(vsftpd.getOptionType())) {
  30. //判断文件是否存在
  31. boolean b = FtpUtil.fileExist(vsftpd.getProjectCode(), vsftpd.getFileName());
  32. if (b) {
  33. ErrorInfo errorInfo = new ErrorInfo("PARAMETER.FAIL", "文件[" + vsftpd.getFileName() + "]已存在!");
  34. errors.add(errorInfo);
  35. }
  36. }
  37. //上传文件(文件若存在则覆盖)
  38. if(CollectionUtils.isEmpty(errors)){
  39. flag = FtpUtil.uploadFile(vsftpd.getFileName(),vsftpd.getByteArry(),vsftpd.getOptionType());
  40. }
  41. } catch (Exception e) {
  42. e.printStackTrace();
  43. ErrorInfo errorInfo = new ErrorInfo("FTP.ERROR","下载失败!服务端异常!");
  44. errors.add(errorInfo);
  45. }
  46. if(!flag){
  47. ErrorInfo errorInfo = new ErrorInfo("FTP.ERROR","上传失败!系统异常!");
  48. errors.add(errorInfo);
  49. }
  50. if(CollectionUtils.isEmpty(errors)){
  51. result.setStatus(true);
  52. }else{
  53. result.setStatus(false);
  54. result.setErrors(errors);
  55. }
  56. LOGGER.info("FtpUploadStrategy.vsftpMethod end");
  57. return result;
  58. }
  59. }

文件下载: FtpDownLoadStrategy

  1. /**
  2. * 文件下载
  3. * 若文件不存在 返回文件不存在的错误信息
  4. * @Auther: 011336
  5. * @Date: 2019/4/24 10:59
  6. */
  7. public class FtpDownLoadStrategy implements IFtpUploadStrategy {
  8.  
  9. private static Logger LOGGER = LoggerFactory.getLogger(FtpDownLoadStrategy.class);
  10.  
  11. @Override
  12. public VsftpResult vsftpMethod(Vsftpd vsftpd){
  13. LOGGER.info("FtpDownLoadStrategy.vsftpMethod start");
  14. VsftpResult result = new VsftpResult();
  15. List<ErrorInfo> errors = new ArrayList<>();
  16. byte[] arryArry = null;
  17. if (StringUtils.isEmpty(vsftpd.getFileName())) {
  18. ErrorInfo errorInfo = new ErrorInfo("PARAMETER.FAIL","参数[fileName]不能为空!");
  19. errors.add(errorInfo);
  20. }
  21. //判断文件是否存在
  22. try {
  23. boolean b = FtpUtil.fileExist(vsftpd.getProjectCode(),vsftpd.getFileName());
  24. if (!b){
  25. ErrorInfo errorInfo = new ErrorInfo("PARAMETER.FAIL","文件[fileName]不存在!");
  26. errors.add(errorInfo);
  27. }
  28. //下载
  29. if(CollectionUtils.isEmpty(errors)){
  30. arryArry = FtpUtil.downloadFile(vsftpd.getProjectCode(),vsftpd.getFileName());
  31. }
  32. } catch (Exception e) {
  33. e.printStackTrace();
  34. ErrorInfo errorInfo = new ErrorInfo("FTP.ERROR","下载失败!服务端异常!");
  35. errors.add(errorInfo);
  36. }
  37. if(arryArry == null){
  38. ErrorInfo errorInfo = new ErrorInfo("FTP.ERROR","下载失败!系统异常!");
  39. errors.add(errorInfo);
  40. }
  41. if(CollectionUtils.isEmpty(errors)){
  42. result.setStatus(true);
  43. result.setByteArry(arryArry);
  44. }else{
  45. result.setStatus(false);
  46. result.setErrors(errors);
  47. }
  48. LOGGER.info("FtpDownLoadStrategy.vsftpMethod end");
  49. return result;
  50. }
  51. }

文件删除: FtpDeleteStrategy

  1. /**
  2. * 文件删除
  3. * 文件若不存在则返回删除成功
  4. * @Auther: 011336
  5. * @Date: 2019/4/24 10:59
  6. */
  7. public class FtpDeleteStrategy implements IFtpUploadStrategy {
  8.  
  9. private static Logger LOGGER = LoggerFactory.getLogger(FtpDeleteStrategy.class);
  10.  
  11. @Override
  12. public VsftpResult vsftpMethod(Vsftpd vsftpd){
  13. LOGGER.info("FtpDeleteStrategy.vsftpMethod start");
  14. VsftpResult result = new VsftpResult();
  15. List<ErrorInfo> errors = new ArrayList<>();
  16. if (StringUtils.isEmpty(vsftpd.getFileName())) {
  17. ErrorInfo errorInfo = new ErrorInfo("PARAMETER.FAIL","参数[fileName]不能为空!");
  18. errors.add(errorInfo);
  19. }
  20. //删除文件
  21. try {
  22. if(CollectionUtils.isEmpty(errors)){
  23. FtpUtil.deleteFile(vsftpd.getProjectCode(),vsftpd.getFileName());
  24. }
  25. } catch (Exception e) {
  26. e.printStackTrace();
  27. ErrorInfo errorInfo = new ErrorInfo("FTP.ERROR","删除失败!服务端异常!");
  28. errors.add(errorInfo);
  29. }
  30.  
  31. if(CollectionUtils.isEmpty(errors)){
  32. result.setStatus(true);
  33. }else{
  34. result.setStatus(false);
  35. result.setErrors(errors);
  36. }
  37. LOGGER.info("FtpDeleteStrategy.vsftpMethod end");
  38. return result;
  39. }
  40. }

获取文件列表:FtpDisplayStrategy

  1. /**
  2. * 获取文件列表
  3. * @Auther: 011336
  4. * @Date: 2019/4/24 10:59
  5. */
  6. public class FtpDisplayStrategy implements IFtpUploadStrategy {
  7.  
  8. private static Logger LOGGER = LoggerFactory.getLogger(FtpDisplayStrategy.class);
  9.  
  10. @Override
  11. public VsftpResult vsftpMethod(Vsftpd vsftpd){
  12. LOGGER.info("FtpDisplayStrategy.vsftpMethod start");
  13. VsftpResult result = new VsftpResult();
  14. List<ErrorInfo> errors = new ArrayList<>();
  15. String[] fileNames = new String[0];
  16. try {
  17. fileNames = FtpUtil.displayFile(vsftpd.getProjectCode());
  18. } catch (Exception e) {
  19. e.printStackTrace();
  20. ErrorInfo errorInfo = new ErrorInfo("FTP.ERROR","获取文件列表失败!服务端异常!");
  21. errors.add(errorInfo);
  22. }
  23. if(CollectionUtils.isEmpty(errors)){
  24. result.setStatus(true);
  25. result.setFileNames(fileNames);
  26. }else{
  27. result.setStatus(false);
  28. result.setErrors(errors);
  29. }
  30. LOGGER.info("FtpDisplayStrategy.vsftpMethod end");
  31. return result;
  32. }
  33. }

提供一个策略接口:

  1. /**
  2. * @Auther: 011336
  3. * @Date: 2019/4/24 11:21
  4. */
  5. public interface IFtpStrategy {
  6. /**
  7. * 统一处理用户请求
  8. * @param vsftpd
  9. * @return
  10. */
  11. VsftpResult vsftpMethod(Vsftpd vsftpd);
  12. }

最主要是我们的 FtpUtil 工具类

  1. /**
  2. * @author 王未011336
  3. * @date 2018/11/04
  4. * ftp服务器文件上传下载
  5. */
  6. public class FtpUtil {
  7. private static Logger LOGGER = LoggerFactory.getLogger(FtpUtil.class);
  8. private static String LOCAL_CHARSET = "GBK";
  9. private static String SERVER_CHARSET = "ISO-8859-1";
  10. private static String host;
  11. private static String port;
  12. private static String username;
  13. private static String password;
  14. private static String basePath;
  15. private static String filePath;
  16. private static String localPath;
  17.  
  18. /**
  19. *读取配置文件信息
  20. * @return
  21. */
  22. public static void getPropertity(){
  23. Properties properties = new Properties();
  24. ClassLoader load = FtpUtil.class.getClassLoader();
  25. InputStream is = load.getResourceAsStream("conf/vsftpd.properties");
  26. try {
  27. properties.load(is);
  28. host=properties.getProperty("vsftpd.ip");
  29. port=properties.getProperty("vsftpd.port");
  30. username=properties.getProperty("vsftpd.user");
  31. password=properties.getProperty("vsftpd.pwd");
  32. //服务器端 基路径
  33. basePath=properties.getProperty("vsftpd.remote.base.path");
  34. //服务器端 文件路径
  35. filePath=properties.getProperty("vsftpd.remote.file.path");
  36. //本地 下载到本地的目录
  37. localPath=properties.getProperty("vsftpd.local.file.path");
  38. } catch (IOException e) {
  39. e.printStackTrace();
  40. }
  41. }
  42.  
  43. /**
  44. * 上传重载
  45. * @param filename 上传到服务器端口重命名
  46. * @param buffer byte[] 文件流
  47. * @return
  48. */
  49. public static boolean uploadFile(String filename, byte[] buffer, String optionType) throws Exception{
  50. getPropertity();
  51. return uploadFile( host, port, username, password, basePath,
  52. filePath, filename, buffer, optionType);
  53. }
  54.  
  55. /**
  56. * 获取文件列表
  57. * @param filePath
  58. * @return
  59. * @throws Exception
  60. */
  61. public static String[] displayFile(String filePath) throws Exception{
  62. getPropertity();
  63. return displayFile(host, port, username, password, basePath, filePath);
  64. }
  65.  
  66. /**
  67. * 删除文件
  68. * @param filePath
  69. * @return
  70. */
  71. public static boolean deleteFile(String filePath, String fileName) throws Exception{
  72. getPropertity();
  73. return deleteFile(host, port, username, password, basePath, filePath, fileName);
  74. }
  75.  
  76. /**
  77. * 判断文件是否存在
  78. * @param filePath
  79. * @return
  80. * @throws Exception
  81. */
  82. public static boolean fileExist(String filePath,String filename) throws Exception{
  83. if(StringUtils.isEmpty(filename)){
  84. return false;
  85. }
  86. getPropertity();
  87. String[] names = displayFile(filePath);
  88. for (String name : names) {
  89. if(filename.equals(name)){
  90. return true;
  91. }
  92. }
  93. return false;
  94. }
  95.  
  96. /**
  97. *下载重载
  98. * @param filePath 要下载的文件所在服务器的相对路径
  99. * @param fileName 要下载的文件名
  100. * @return
  101. */
  102. public static byte[] downloadFile(String filePath,String fileName) throws Exception{
  103. getPropertity();
  104. return downloadFile( host, port, username, password, basePath,
  105. filePath, fileName);
  106. }
  107.  
  108. /**
  109. * Description: 向FTP服务器上传文件
  110. * @param host FTP服务器hostname
  111. * @param port FTP服务器端口
  112. * @param username FTP登录账号
  113. * @param password FTP登录密码
  114. * @param basePath FTP服务器基础目录
  115. * @param filePath FTP服务器文件存放路径。例如分日期存放:/2015/01/01。文件的路径为basePath+filePath
  116. * @param fileName 上传到FTP服务器上的文件名
  117. * @return 成功返回true,否则返回false
  118. */
  119. public static boolean uploadFile(String host, String port, String username, String password, String basePath,
  120. String filePath, String fileName, byte[] buffer, String optionType) throws Exception{
  121. FTPClient ftp = new FTPClient();
  122. try {
  123. fileName = new String(fileName.getBytes(LOCAL_CHARSET));
  124. boolean result = connectFtp(ftp, host, port, username, password, basePath, filePath);
  125. if(!result){
  126. return result;
  127. }
  128. //为了加大上传文件速度,将InputStream转成BufferInputStream , InputStream input
  129. InputStream inputStream = new ByteArrayInputStream(buffer);
  130. //加大缓存区
  131. ftp.setBufferSize(1024*1024);
  132. //设置上传文件的类型为二进制类型
  133. ftp.setFileType(FTP.BINARY_FILE_TYPE);
  134. if(FtpConstants.REPLACE.equals(optionType)){
  135. ftp.deleteFile(fileName);
  136. }
  137. //上传文件
  138. if (!ftp.storeFile(fileName, inputStream)) {
  139. return false;
  140. }
  141. inputStream.close();
  142. ftp.logout();
  143. } catch (IOException e) {
  144. LOGGER.info(e.getMessage());
  145. e.printStackTrace();
  146. throw e;
  147. } finally {
  148. if (ftp.isConnected()) {
  149. try {
  150. ftp.disconnect();
  151. } catch (IOException ioe) {
  152. }
  153. }
  154. }
  155. return true;
  156. }
  157.  
  158. /**
  159. * Description: 从FTP服务器下载文件
  160. * @param host FTP服务器hostname
  161. * @param port FTP服务器端口
  162. * @param username FTP登录账号
  163. * @param password FTP登录密码
  164. * @param basePath FTP服务器上的相对路径
  165. * @param fileName 要下载的文件名
  166. * @return
  167. */
  168. public static byte[] downloadFile(String host, String port, String username, String password, String basePath,
  169. String filePath, String fileName) throws Exception{
  170. FTPClient ftp = new FTPClient();
  171. try {
  172. fileName = new String(fileName.getBytes(LOCAL_CHARSET));
  173. boolean result = connectFtp(ftp, host, port, username, password, basePath, filePath);
  174. if(!result){
  175. return null;
  176. }
  177. FTPFile[] fs = ftp.listFiles();
  178. boolean flag = true;
  179. for (FTPFile ff : fs) {
  180. if (ff.getName().equals(fileName)) {
  181. InputStream input = ftp.retrieveFileStream(ff.getName());
  182. BufferedInputStream in = new BufferedInputStream(input);
  183. ByteArrayOutputStream outStream = new ByteArrayOutputStream();
  184. byte[] buffer = new byte[1024];
  185. int len = -1;
  186. while((len = in.read(buffer)) != -1){
  187. outStream.write(buffer, 0, len);
  188. }
  189. outStream.close();
  190. in.close();
  191. byte[] arryArry = outStream.toByteArray();
  192. return arryArry;
  193. }
  194. }
  195. if(flag) {
  196. LOGGER.info("服务器端文件不存在...");
  197. return null;
  198. }
  199. ftp.logout();
  200. } catch (IOException e) {
  201. LOGGER.info(e.getMessage());
  202. e.printStackTrace();
  203. throw e;
  204. } finally {
  205. if (ftp.isConnected()) {
  206. try {
  207. ftp.disconnect();
  208. } catch (IOException ioe) {
  209. }
  210. }
  211. }
  212. return null;
  213. }
  214.  
  215. /**
  216. * 获取服务器文件名列表
  217. * @param host
  218. * @param port
  219. * @param username
  220. * @param password
  221. * @param basePath
  222. * @param filePath
  223. * @return
  224. * @throws Exception
  225. */
  226. public static String[] displayFile(String host, String port, String username, String password, String basePath,
  227. String filePath) throws Exception{
  228. FTPClient ftp = new FTPClient();
  229. try {
  230. boolean result = connectFtp(ftp, host, port, username, password, basePath, filePath);
  231. if(!result){
  232. return null;
  233. }
  234. String[] names = ftp.listNames();
  235. ftp.logout();
  236. return names;
  237. } catch (IOException e) {
  238. LOGGER.info(e.getMessage());
  239. e.printStackTrace();
  240. throw e;
  241. } finally {
  242. if (ftp.isConnected()) {
  243. try {
  244. ftp.disconnect();
  245. } catch (IOException ioe) {
  246. }
  247. }
  248. }
  249. }
  250.  
  251. /**
  252. * 删除文件
  253. * @param host
  254. * @param port
  255. * @param username
  256. * @param password
  257. * @param basePath
  258. * @param filePath
  259. * @return
  260. */
  261. public static boolean deleteFile(String host, String port, String username, String password, String basePath,
  262. String filePath,String fileName) throws Exception{
  263. FTPClient ftp = new FTPClient();
  264. boolean b = false;
  265. try {
  266. boolean result = connectFtp(ftp, host, port, username, password, basePath, filePath);
  267. if(!result){
  268. return b;
  269. }
  270. b = ftp.deleteFile(fileName);
  271. ftp.logout();
  272. } catch (IOException e) {
  273. LOGGER.info(e.getMessage());
  274. e.printStackTrace();
  275. throw e;
  276. } finally {
  277. if (ftp.isConnected()) {
  278. try {
  279. ftp.disconnect();
  280. } catch (IOException ioe) {
  281. }
  282. }
  283. }
  284. return b;
  285. }
  286.  
  287. /**
  288. * 连接ftp服务器并切换到目的目录
  289. * 调用此方法需手动关闭ftp连接
  290. * @param ftp
  291. * @param host
  292. * @param port
  293. * @param username
  294. * @param password
  295. * @param basePath
  296. * @param filePath
  297. * @return
  298. */
  299. private static boolean connectFtp( FTPClient ftp,String host, String port, String username,
  300. String password, String basePath, String filePath) throws Exception{
  301. boolean result = false;
  302. try {
  303. int portNum = Integer.parseInt(port);
  304. int reply;
  305. // 连接FTP服务器
  306. ftp.connect(host, portNum);
  307. // 如果采用默认端口,可以使用ftp.connect(host)的方式直接连接FTP服务器
  308. ftp.login(username, password);
  309. reply = ftp.getReplyCode();
  310. if (!FTPReply.isPositiveCompletion(reply)) {
  311. ftp.disconnect();
  312. return result;
  313. }
  314. // 开启服务器对UTF-8的支持,如果服务器支持就用UTF-8编码,否则就使用本地编码(GBK).
  315. if (FTPReply.isPositiveCompletion(ftp.sendCommand("OPTS UTF8", "ON"))) {
  316. LOCAL_CHARSET = "UTF-8";
  317. }
  318. ftp.setControlEncoding(LOCAL_CHARSET);
  319. //切换到上传目录
  320. if (!ftp.changeWorkingDirectory(basePath+filePath)) {
  321. //如果目录不存在创建目录
  322. String[] dirs = filePath.split("/");
  323. String tempPath = basePath;
  324. for (String dir : dirs) {
  325. if (null == dir || "".equals(dir)) {
  326. continue;
  327. }
  328. tempPath += "/" + dir;
  329. if (!ftp.changeWorkingDirectory(tempPath)) {
  330. if (!ftp.makeDirectory(tempPath)) {
  331. return result;
  332. } else {
  333. ftp.changeWorkingDirectory(tempPath);
  334. }
  335. }
  336. }
  337. }
  338. result = true;
  339. } catch (IOException e) {
  340. LOGGER.info(e.getMessage());
  341. e.printStackTrace();
  342. throw e;
  343. }
  344. return result;
  345. }
  346. }

拦截器权限校验这边涉及到太多业务,读者可止步于此,但我还是要贴一下代码

配置拦截器: FilterManager

  1. /**
  2. * @Auther: 011336
  3. * @Date: 2019/3/28 19:17
  4. */
  5. @Configuration
  6. public class FilterManager implements WebMvcConfigurer {
  7.  
  8. @Autowired
  9. private AuthorityInterceptor loginInterceptor;
  10. @Override
  11. public void addInterceptors(InterceptorRegistry registry){
  12.  
  13. registry.addInterceptor(loginInterceptor)
  14. .addPathPatterns("/**");
  15. }
  16. }

拦截器具体实现: AuthorityInterceptor

  1. /**
  2. * 拦截器做权限验证
  3. * 权限信息接SI接口管理系统,调用者需提供白名单用户名,和白名单密码(MD5加密)
  4. * 本服务根据调用者在SI中的项目编码projectCode为调用者创建独立目录地址
  5. * requestUri 接口地址
  6. * onlineInterfaceCode 接口线上编码
  7. * 从SI同步而来的白名单信息包含此接口的线上接口编码onlineInterfaceCode,本项目维护了onlineInterfaceCode与requestUri之间的对应关系
  8. * 目的:使系统兼容提供多个接口的情况
  9. * @Auther: 011336
  10. * @Date: 2019/4/28 19:11
  11. */
  12. @Component
  13. public class AuthorityInterceptor implements HandlerInterceptor {
  14.  
  15. private static Logger LOGGER = LoggerFactory.getLogger(AuthorityInterceptor.class);
  16.  
  17. @Autowired
  18. private IWhiteListService whiteListService;
  19. /**
  20. * 拦截器做权限验证
  21. * @param request
  22. * @param response
  23. * @param handler
  24. * @return
  25. * @author 011336
  26. * @date 2019/04/24
  27. * @throws Exception
  28. */
  29. @Override
  30. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception{
  31. String whiteListUsername = request.getHeader("whiteListUsername");
  32. String whiteListPassword = request.getHeader("whiteListPassword");
  33. String projectCode = request.getHeader("projectCode");
  34. if(StringUtils.isNotEmpty(projectCode)){
  35. Optional<String> userName = Optional.ofNullable(whiteListUsername);
  36. Optional<String> passWord = Optional.ofNullable(whiteListPassword);
  37. String requestUri = request.getRequestURI();
  38. Map<String,Object> condition = new HashMap<>();
  39. condition.put("requestUri",requestUri);
  40. condition.put("projectCode",projectCode);
  41. WhiteList whiteList = whiteListService.query(condition);
  42. Optional<WhiteList> whiteOptional = Optional.ofNullable(whiteList);
  43. WhiteList white = whiteOptional.orElse(new WhiteList());
  44. if(userName.orElse(UUID.randomUUID().toString()).equals(white.getWhiteListUsername()) &&
  45. passWord.orElse(UUID.randomUUID().toString()).equals(white.getWhiteListPassword())) {
  46. LOGGER.info("["+projectCode+"]权限认证成功!");
  47. return true;
  48. }
  49. }
  50. //重置response
  51. response.reset();
  52. response.setCharacterEncoding("UTF-8");
  53. response.setContentType("application/json;charset=UTF-8");
  54. PrintWriter pw = response.getWriter();
  55. VsftpResult result = new VsftpResult();
  56. result.setStatus(false);
  57. ErrorInfo errorInfo = new ErrorInfo("AUTHORITY.FAIL", "权限验证失败!");
  58. List<ErrorInfo> errors = new ArrayList<>();
  59. errors.add(errorInfo);
  60. result.setErrors(errors);
  61. pw.write(JsonUtils.objectToJson(result));
  62. pw.flush();
  63. pw.close();
  64. LOGGER.info("["+projectCode+"]权限认证失败!"+ JsonUtils.objectToJson(result));
  65. return false;
  66. }
  67. @Override
  68. public void postHandle(HttpServletRequest request, HttpServletResponse response,
  69. Object handler,ModelAndView model) throws Exception{
  70. }
  71. @Override
  72. public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
  73. Object handler,Exception ex) throws Exception{
  74. }
  75. }

现这样吧...心情不好

开发FTP服务接口,对外提供接口服务的更多相关文章

  1. springboot+CXF开发webservice对外提供接口(转)

    文章来源:http://www.leftso.com/blog/144.html 1.项目要对外提供接口,用webservcie的方式实现 2.添加的jar包 maven: <dependenc ...

  2. 使用WCF对外提供接口

    本篇将通过WCF以webservices的方式对外提供接口.同时使用NUnit对webservices中的方法进行单元测试. 开发契约 contract Contract项目为类库项目,该项目下会包含 ...

  3. Frp内网穿透搭建,家庭主机对外提供接口,支持ssh访问

    Frp内网穿透搭建,家庭主机对外提供接口,支持ssh访问 1.使用场景: 需求1.家中服务器 ubuntu 主机,跑接口服务,需要对外暴漏, 需求2.同时需要在外网ssh远程 ​ 关键词: frp内网 ...

  4. grpc-gateway:grpc对外提供http服务的解决方案

    我所在公司的项目是采用基于Restful的微服务架构,随着微服务之间的沟通越来越频繁,就希望可以做成用rpc来做内部的通讯,对外依然用Restful.于是就想到了google的grpc. 使用grpc ...

  5. Java服务器对外提供接口以及Android端向服务器请求数据

    转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/5056780.html 讲解下java服务器是如何对移动终端提供接口的,以什么数据格式提供出去,移动端又是怎么 ...

  6. WPF内嵌WCF服务对外提供接口

    要测试本帖子代码请记得管理员权限运行vs. 我写这个帖子的初衷是在我做surface小车的时候有类似的需求,感觉这个功能还挺有意思的,所以就分享给大家,网上有很多关于wcf的文章 我就不一一列举了.公 ...

  7. windows服务中对外提供API接口

    public class SendMqService { private static bool isExcute = true; private static HttpListener listen ...

  8. Windows 端口和所提供的服务

    一 .端口大全 端口:0 服务:Reserved 说明:通常用于分析操作系统.这一方法能够工作是因为在一些系统中“0”是无效端口,当你试图使用通常的闭合端口连接它时将产生不同的结果.一种典型的扫描,使 ...

  9. C++中模块(Dll)对外暴露接口的方式

    总结下C++中模块(Dll)对外暴露接口的方式: (1)导出API函数的方式这种方式是Windows中调用DLL接口的最基本方式,GDI32.dll, User32.dll都是用这种方式对外暴露系统A ...

随机推荐

  1. tricky c++ new(this)

    题目如下:问下列代码的打印结果为0吗? #include <stdlib.h> #include <iostream> using namespace std; struct  ...

  2. LaTeX技巧472:定义一个LaTeX参考文献不带编号且有缩进的方法

    LaTeX_Fun的博客 LaTeX技巧381:参考文献项第二行缩进如何定义? \makeatletter\renewenvironment{thebibliography}[1]{\section* ...

  3. [css]画圆形标签

    画圆形标签的窍门: 圆形是在padding和margin中间同时是padding的内切圆也是margin的外接圆 .circle{ width: 20px; height: 20px; display ...

  4. CCF_201612-2_火车购票

    http://115.28.138.223/view.page?gpid=T46 水. #include<iostream> #include<cstring> #includ ...

  5. 使用logstash结合logback收集微服务日志

    因为公司开发环境没有装elk,所以每次查看各个微服务的日志只能使用如下命令 这样子访问日志是并不方便,于是想为每个微服务的日志都用logstash收集到一个文件out中,那以后只要输出这个文件则可查看 ...

  6. 【转】JAVA BIO与NIO、AIO的区别

    Java中IO的模型分为三种,同步阻塞的BIO.同步非阻塞的NIO.异步非阻塞的AIO. BIO[同步阻塞] 在JDK1.4出来之前,我们建立网络连接的时候采用BIO模式,需要先在服务端启动一个Ser ...

  7. lwip的netif状态管理

    netif的状态变化可以设置回调函数, 主要有三项变化, 1 netif up or down,address change,address state change(IPv6) 2 link up ...

  8. python2 + Django 中文传到模板页面变Unicode乱码问题

    1.确保views页面首行设置了默认编码   # -*-coding:utf-8 -*- 2.确保html页面的编码为 utf-8 3.确保项目setting文件设置了 LANGUAGE_CODE = ...

  9. Red Team 指南-第1章 红队和红队概述

    第1章 红队和红队概述 贡献者:Tony Kelly @infosectdk # 翻译者 BugMan 什么是红队?它来自哪里? 红队的起源是军事起源.人们意识到,为了更好地防御, 需要攻击自己的防御 ...

  10. JS用map做接口数据映射

    · 接口做数据映射的好处:前端页面自定义的字段不需要和后端字段相同,后端修改字段前端不受影响. · 从接口得到数据 res: let r = res.map(item => { return { ...