javascript
ftpclient读取服务器文件能获得文件名文件大小0_Spring WEB工程整合使用FTP,ftp文本文件解析入库,文件上传下载
友情提示:文章比較長,方法都是有一層層封裝的,閱讀需要按照文章順序閱讀
首先寫一個簡單的FTP工具類,先實現最基本的文件上傳,下載,刪除,拷貝功能。這里操作FTP是用的commons-net-3.3.jar中的org.apache.commons.net.ftp中的對象
package com.wzh.config.utils;import org.apache.commons.net.ftp.FTP;import org.apache.commons.net.ftp.FTPClient;import org.apache.commons.net.ftp.FTPFile;import org.apache.commons.net.ftp.FTPReply;import org.apache.log4j.Logger;import java.io.*;import java.nio.charset.Charset;import java.util.ArrayList;import java.util.List;/** * @author wzh * @create 2018-05-06 23:03 * @desc ${操作FTP文件工具類} **/public class FtpUtils { private static Logger log = Logger.getLogger(FtpUtils.class); //本地編碼集對象 private static String encode = Charset.defaultCharset().toString(); // FTP編碼為iso-8859-1 private static final String SERVER_CHARSET = "ISO-8859-1"; //FTP下載時讀入內存的大小 private static final int BUFFER_SIZE = 1024000; /** * 獲取FTP連接對象,連接FTP成功返回FTP對象, * 連接FTP失敗超過最大次數返回null,使用前請判斷是否為空 * @param ftpHost 服務器ip * @param ftpPort 服務器端口 * @param ftpUserName 用戶名 * @param ftpPassword 密碼 * @return FTPClient FTP連接對象 */ public static FTPClient getFTPClient(String ftpHost, int ftpPort, String ftpUserName, String ftpPassword) { //FTP連接對象 FTPClient ftpClient = null; try { ftpClient = new FTPClient(); //設置FTP服務器IP和端口 ftpClient.connect(ftpHost,ftpPort); //設置超時時間,毫秒 ftpClient.setConnectTimeout(50000); //登錄FTP ftpClient.login(ftpUserName,ftpPassword); //設置被動傳輸模式 ftpClient.enterLocalPassiveMode(); //ftpClient.enterRemotePassiveMode(); //二進制傳輸 ftpClient.setFileType(FTP.BINARY_FILE_TYPE); //設置讀入內存文件大小 ftpClient.setBufferSize(BUFFER_SIZE); //獲取FTP連接狀態碼 ,大于等于200 小于300狀態碼表示連接正常 int connectState = ftpClient.getReplyCode(); //連接失敗重試 int reNum = 0; while (!FTPReply.isPositiveCompletion(connectState) && reNum < 3) { ftpClient.disconnect(); ++reNum; ftpClient.login(ftpUserName,ftpPassword); } if (reNum < 3) { log.info("FTP連接成功"); } else { ftpClient = null; log.error("FTP連接失敗"); } } catch (Exception e) { log.error(e.getMessage(), e); } return ftpClient; } /** *斷開FTP * @param ftpClient fpt連接對象 */ public static void closeFTP(FTPClient ftpClient) { if (null != ftpClient) { try { //登出FTP ftpClient.disconnect(); log.info("登出FTP成功"); } catch (IOException e) { log.error(e.getMessage(), e); } finally { try { //斷開FTP ftpClient.disconnect(); log.info("斷開FTP成功"); } catch (IOException e) { log.error(e.getMessage(), e); } } } } /** * 根據FTP編碼集轉換文件路徑,防止中文亂碼,并設置FTP連接的編碼集 * @param ftpClient FTP連接對象 * @param path 文件路徑 * @return 轉碼后的文件路徑 */ public static String changeEncode(FTPClient ftpClient,String path) throws IOException { synchronized (encode) { int status = ftpClient.sendCommand("OPTS UTF8","ON"); //判斷FTP服務器是否支持UTF -8,支持使用UTF-8 否則使用本地編碼集 if(FTPReply.isPositiveCompletion(status)) { encode = "UTF-8"; } log.info("FTP使用編碼集:" + encode); ftpClient.setControlEncoding(encode); path = new String(path.getBytes(encode),SERVER_CHARSET); } return path; } /** * 獲取文件后綴 * @param fileName 文件名或文件全路徑 * @return 文件后綴 */ public static String getSuffix(String fileName) { String suffix = ""; int index = fileName.lastIndexOf("."); if(index != -1) { suffix = fileName.substring(index); log.info("獲取文件后綴名成功,文件名:" + fileName + " 后綴名:" + suffix); }else{ log.warn("獲取文件后綴名失敗,文件名" + fileName); } return suffix; } /** * 獲取FTP指定文件大小 * @param ftpClient ftp連接對象 * @param fileName ftp文件服務器路徑 如:/public/file/xxx.text * @return 文件大小,獲取失敗返回-1 */ public static Long getFtpFileSize(FTPClient ftpClient, String fileName) { FTPFile[] files = null; Long fileSize = -1L; try { files = ftpClient.listFiles(changeEncode(ftpClient,fileName)); //因為指定了具體的文件名,這里只取數組0位 if (null != files && files.length > 0) { log.info("文件個數:" + files.length + " 文件名:" + files[0].getName() + " 文件大小:" + files[0].getSize()); fileSize = files[0].getSize(); } } catch (IOException e) { fileSize = 1L; log.error(e.getMessage(),e); } return fileSize; } /** *下載FTP上指定文件路徑文件 * @param ftpClient FTP連接對象 * @param filePath 文件路徑+文件名 例如:/public/file/a.txt * @param downPath 下載文件保存的路徑 * @param newFileName 新的文件名 例如:newFileName * @return */ public static boolean downLoadFtpFile(FTPClient ftpClient, String filePath,String downPath, String newFileName) { //默認失敗 boolean flag = false; //獲取文件后綴 String suffix = getSuffix(filePath); //下載的文件對象 File dwonFile = new File(downPath + File.separator + newFileName + suffix); try { OutputStream out = new FileOutputStream(dwonFile); flag = ftpClient.retrieveFile(changeEncode(ftpClient,filePath),out); out.flush(); out.close(); if(flag) { log.info("下載文件成功,文件路徑:" + filePath); }else{ log.error("下載文件失敗,文件路徑:" + filePath); } } catch (Exception e) { log.error(e.getMessage(),e); } return flag; } /** * FTP文件上傳工具類 * @param ftpClient 連接對象 * @param filePath 本地文件路徑 /xxxx/xx.txt * @param ftpPath ftp儲存路徑 * @param newFileName ftp保存的文件名 * @return true 下載成功,false 下載失敗 */ public static boolean uploadFile(FTPClient ftpClient,String filePath,String ftpPath, String newFileName) { boolean flag = false; InputStream in = null; try { //獲取文件后綴 String suffix = getSuffix(filePath); //路徑轉碼,處理中文 ftpPath = changeEncode(ftpClient,ftpPath); newFileName = changeEncode(ftpClient,newFileName + suffix); //判斷目標文件夾是否存在,不存在就創建 if(!ftpClient.changeWorkingDirectory(ftpPath)) { ftpClient.makeDirectory(ftpPath); ftpClient.changeWorkingDirectory(ftpPath); } //上傳文件 File file = new File(filePath); in = new FileInputStream(file); flag = ftpClient.storeFile(newFileName,in); if(flag) { log.info("文件上傳成功:" + filePath); } } catch (Exception e) { log.error(e.getMessage(),e); } finally { try { if(in != null) { in.close(); } } catch (IOException e) { log.error(e.getMessage(),e); } } return flag; } /** * FTP上文復制文件到另外一個路徑 * @param ftpClient ftp連接對象 * @param oldFtpPath 源文件儲存路徑 xxx/xxx.txt * @param newFtpPath 新路徑 /public/file/ * @param newFileName 新文件名 * @return true 下載成功,false 下載失敗 */ public static boolean copyFile(FTPClient ftpClient,String oldFtpPath,String newFtpPath, String newFileName) { boolean flag = false; ByteArrayInputStream in = null; ByteArrayOutputStream out = null; try { out = new ByteArrayOutputStream(); //獲取文件后綴 String suffix = getSuffix(oldFtpPath); //先讀入內存,綁定out輸出流,然后再轉換為輸入流 String encodeOldPath = changeEncode(ftpClient,oldFtpPath); ftpClient.retrieveFile(encodeOldPath,out); in = new ByteArrayInputStream(out.toByteArray()); //切換工作目錄,沒有就創建 String encodeNewPath = changeEncode(ftpClient,newFtpPath); if(!ftpClient.changeWorkingDirectory(encodeNewPath)) { ftpClient.makeDirectory(encodeNewPath); ftpClient.changeWorkingDirectory(encodeNewPath); } //復制文件 flag = ftpClient.storeFile(changeEncode(ftpClient,newFileName + suffix),in); out.flush(); out.close(); in.close(); if (flag) { log.info("文件復制成功,源文件:" + oldFtpPath + " 新路徑:" + newFtpPath + newFileName); } else { throw new BusinessException("文件復制失敗,源文件:" + oldFtpPath); } } catch (Exception e) { log.error(e.getMessage(),e); } return flag; } /** * 刪除Ftp上的文件 * @param ftpClient 連接對象 * @param filePath 服務器文件路徑 /public/file/xxx.txt * @return true 成功,false 失敗 */ public static boolean delectFile(FTPClient ftpClient,String filePath) { boolean flag = false; try { flag = ftpClient.deleteFile(changeEncode(ftpClient,filePath)); if(flag) { log.info("刪除文件成功:" + filePath); }else{ log.error("刪除文件失敗:" + filePath); } } catch (IOException e) { log.error(e.getMessage(),e); } return flag; } /** * 文件移動 * @param ftpClient fpt連接對象 * @param oldFtpPath 文件原路徑 /public/old/xxx.txt * @param newFtpPath 文件新路徑 /public/new/ * @param newFileName 文件名 * @return true 成功,false 失敗 */ public static boolean moveFile(FTPClient ftpClient,String oldFtpPath,String newFtpPath, String newFileName) { boolean flag = false; try { //文件后綴 String suffix = getSuffix(oldFtpPath); //路徑編碼 String encodeOldPath = changeEncode(ftpClient,oldFtpPath); String encodeNewPath = changeEncode(ftpClient,newFtpPath); String encodeNewFileName = changeEncode(ftpClient,newFileName + suffix); //切換工作目錄 if(!ftpClient.changeWorkingDirectory(encodeNewPath)) { ftpClient.makeDirectory(encodeNewPath); ftpClient.changeWorkingDirectory(encodeNewPath); } //轉存 flag = ftpClient.rename(encodeOldPath, encodeNewFileName); if(flag) { log.info("文件轉存成功:" + oldFtpPath); }else { log.error("文件轉存失敗:" + oldFtpPath); } } catch (IOException e) { log.error(e.getMessage(),e); } return flag; } /** * 讀取Ftp文本文件,返回行數據集合 * @param ftpClient ftp連接對象 * @param filePath 文件路徑 /public/file/xxx.txt * @param encode 解析文件編碼集 * @return 行數據集合 */ public static List redFtpFileWithLine(FTPClient ftpClient, String filePath, String encode) { List lineList = new ArrayList(); InputStream in = null; BufferedReader reader = null; try { //獲取文件流數據 in = ftpClient.retrieveFileStream(changeEncode(ftpClient,filePath)); if(in == null) { throw new BusinessException("獲取文件流失敗:" + filePath); } reader = new BufferedReader(new InputStreamReader(in,encode)); String inLine; while ((inLine = reader.readLine()) != null) { lineList.add(inLine); } //關閉流 if(reader != null) { reader.close(); } in.close(); /* retrieveFileStream使用了流,需要釋放一下,不然會返回null 方法一:主動調用一次getReply()把接下來的226消費掉 方法二:主動調用一次completePendingCommand(),把流釋放掉 */ ftpClient.getReply(); } catch (Exception e) { log.error(e.getMessage(),e); } return lineList; } /** * 獲取文件輸出流 * @param ftpClient ftp連接對象 * @param filePath 文件路徑 * @param out 文件輸出流 */ public void readFileWithOutputStream(FTPClient ftpClient, String filePath, OutputStream out) { try { if(out == null) { throw new BusinessException("輸出流為null"); } ftpClient.retrieveFile(filePath,out); out.flush(); out.close(); } catch (Exception e) { log.error(e.getMessage(),e); } }}上面只是最簡單的,可以在本地操作ftp上傳下載,在web里面還是有些區別。這里既然是通過spring進行操作,我們不妨在做一些封裝,簡化在項目中的操作。例如我們操作FTP的時候,必要的東西例如,ip,端口,賬號,密碼,這些都是很少進行變化的,但是又是在項目中經常用的,這里提供一個思路,可以在項目啟動的時候,把這些信息加載到內存或者緩存中。
FtpBean對象,這里展示是省略了get set那些方法的。
package com.wzh.config.framework.domain;import org.apache.ibatis.type.Alias;/** * @author wzh * @create 2018-05-27 20:14 * @desc ${ftp 對象,用于存儲ftp賬戶信息} **/@Alias("ftpBean")public class FtpBean { /** * fpt別名 */ private String ftpName; /** * ftp服務器ip */ private String ftpHost; /** * ftp服務器端口 */ private String ftpPort; /** * 賬號名 */ private String ftpUserName; /** * 密碼 */ private String ftpPassword;Spring 在項目啟動的時候加載一些從數據庫中查詢的常量方式很多,可以在xml中配置bean,然后寫init方法,也可以使用注解,或者繼承某些類。這篇博文寫得比較詳細,想詳細了解的可以看下這篇文章
https://blog.csdn.net/honghailiang888/article/details/73333821
因為整合的demo是基于SpringBoot做的,boot中提倡少xml配置文件,所以這里提供一種基于@PostConstruct注解的方式,加載了此注解的方法,會在Spring啟動完成后第一時間執行。
把之前的FtpUtils再進行一下封裝,這里特別說一下,部分方法沒有測試,只是單純的寫了,如果拿來實際使用,需要再測試一下。這里先把文件在線解析,上傳下載,文件流的方法單獨說明,其他的方法就不一一演示了,在文末會把代碼貼出來。
在項目中有這么一個場景,就是用戶上傳實體文件入庫,有excel的,這種場景一般是在用戶端直接頁面操作,解析后入庫,還有一種是跨平臺實體文件同步,有的時候有某些大批量的數據需要跨平臺同步,如果直接通過接口的方式調用,文件條數如果是幾十萬,接口性能并不高,這個時候可以通過ftp文件服務器的方式同步,大體有兩種,第一種是接口主動通知服務端,文件已經放到ftp服務器上,還有一種就是定時任務固定時間掃碼目錄,兩種方式只是觸發機制不一樣,當時處理邏輯都是相同的。
文本文件解析方法,這里為了作為通用方法,用了下泛型和反射
/** * 解析txt實體文件并轉換為對應的list集合,如果沒有分隔符,用String接收 * 需注意實體類與字符串拆分后的順序需相同,排除final 屬性不進行設置值 * 其實還有一種方案就是可以用xml等配置文件進行配置文件映射,屬性類型,這里為了簡單就直接要求順序相同 * @param ftpName ftp別名 * @param filePath 服務器文件路徑 * @param encode 文件編碼集 * @param regex 文件數據分隔符 * @param obj 解析映射的對象 * @param simpleDateFormat 解析映射的對象 * @param 對象泛型 * @return 返回解析后的集合 */ public List readFileWithLine(String ftpName, String filePath, String encode, String regex, String simpleDateFormat,T obj) throws Exception{ //解析后返回的數據集合 List clazzes = new ArrayList(); FTPClient ftpClient = linkFtp(ftpName); if(null != ftpClient) { List info = FtpUtils.redFtpFileWithLine(ftpClient, filePath, encode); if(null != info && !info.isEmpty()) { if(StringUtils.isBlank(regex)) { // 無分隔符,判斷為String 集合 clazzes.addAll((Collection extends T>) info); }else { for(String str : info) { // 拆分行數據 String [] line = str.split(regex); //因為JDK用的1.9 所以沒有直接newInstance,如果是低版本的jdk 可以直接getClass().newInstance T t = (T) obj.getClass().getDeclaredConstructor().newInstance(); // 獲取文件屬性數組 Field[] fielders = t.getClass().getDeclaredFields(); // 循環排除final屬性 List fieldList = new ArrayList(); for(Field cell : fielders) { if(!Modifier.isFinal(cell.getModifiers())) { // 非final的屬性才進行處理 fieldList.add(cell); } } // 數據和對象映射要求完全對應,所以這里取對象下標 for(int i = 0; i < fieldList.size(); i++) { Field field = fieldList.get(i); // 設置權限 field.setAccessible(true); // 判斷數據類型進行轉換,這里只做了幾種常見類型的判斷,如果有需要可以繼續添加 String type = field.getType().getName(); try { if("java.lang.Integer".equals(type) || "int".equals(type)) { field.set(t,NumberUtils.toInt(line[i])); } else if("java.lang.Double".equals(type) || "double".equals(type)) { field.set(t,NumberUtils.toDouble(line[i])); } else if("java.lang.Float".equals(type) || "float".equals(type)) { field.set(t,NumberUtils.toFloat(line[i])); } else if("java.lang.Long".equals(type) || "long".equals(type)) { field.set(t,NumberUtils.toLong(line[i])); } else if("java.lang.Short".equals(type) || "short".equals(type)) { field.set(t,NumberUtils.toShort(line[i])); } else if("java.lang.Boolean".equals(type) || "boolean".equals(type)) { field.set(t, BooleanUtils.toBoolean(line[i])); } else if("java.util.Date".equals(type) || "Date".equals(type)) { SimpleDateFormat sdf=new SimpleDateFormat(simpleDateFormat); if(StringUtils.isBlank(line[i])) { field.set(t, null); }else{ field.set(t, sdf.parse(line[i])); } } else { field.set(t, line[i]); } }catch (Exception e){ log.error(e.getMessage(),e); } } // 添加數據 clazzes.add(t); } } } } return clazzes; }測試一下,首先弄一個實體文件
一個實體類User,省略get set 方法
package domin;import java.util.Date;/** * * * * @author wzh * @version 2018-06-18 16:43 * @see [相關類/方法] (可選) **/public class User { private String name; private int age; private Date birthday; public User() { super(); }}junit 測試
import base.BaseJunit;import com.wzh.config.utils.FtpManagerUtils;import domin.User;import org.junit.Ignore;import org.junit.Test;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import java.util.Date;import java.util.List;/** * * * @author wzh * @version 2018-06-18 16:16 * @see [相關類/方法] (可選) **/public class ftpTest extends BaseJunit { @Autowired @Qualifier(value = "ftpManagerUtils") private FtpManagerUtils ftpManagerUtils; @Test public void readTextTest() { User user = new User(); try { //對象文本文件 List list = ftpManagerUtils.readFileWithLine("FTP_USER_SYSTEM", "/file/userinfo.txt","utf-8","|","yyyy-MM-dd",user); //字符串集合文件文件 List strlist = ftpManagerUtils.readFileWithLine("FTP_USER_SYSTEM", "/file/userinfo.txt","utf-8","","yyyy-MM-dd",new String()); System.out.println(list); System.out.println(strlist); } catch (Exception e) { e.printStackTrace(); } }}通過截圖我們可以看到不管是字符串接收行數據還是對象接收,都成功解析了,這個時候就可以根據自身的業務邏輯進行處理入庫等操作了。
在文件上傳服務器這一塊,處理的思路一般有兩種,如果項目比較小,就直接上傳到工程目錄下,或者把工程目錄掛載出去,把其他文件服務器的磁盤掛到工程目錄下的文件服務器。還有一種就是專門的文件服務器,所有的文件都上傳到文件服務器,這里做一個用戶端上傳文件后直接把文件上傳到ftp服務器上的處理方式。
文件上傳工具類,這里是用戶上傳后直接上傳ftp的場景,如果是先存工程,再傳服務器,可以用另外一個方法
/** * 上傳文件到ftp服務器 * @param ftpName ftp別名 * @param file 文件對象 * @param ftpPath ftp 服務器保存路徑 * @param newFileName 保存的文件名 * @return 上傳是否成功過 */ public boolean upLoadFile(String ftpName, MultipartFile file, String ftpPath, String newFileName){ //默認失敗 boolean flag = false; FTPClient ftpClient = linkFtp(ftpName); InputStream in = null; if (null != ftpClient) { try { // 獲取文件名 String fileName = file.getOriginalFilename(); // 獲取文件后綴名 String suffix = FtpUtils.getSuffix(fileName); // 路徑轉碼,處理中文 ftpPath = FtpUtils.changeEncode(ftpClient,ftpPath); newFileName = FtpUtils.changeEncode(ftpClient,newFileName + suffix); // 判斷目標文件夾是否存在,不存在就創建 if(!ftpClient.changeWorkingDirectory(ftpPath)) { ftpClient.makeDirectory(ftpPath); ftpClient.changeWorkingDirectory(ftpPath); } in = file.getInputStream(); flag = ftpClient.storeFile(newFileName,in); if(flag) { log.info("文件上傳成功:" + fileName); } }catch (Exception e) { log.error("文件上傳失敗:" + e.getMessage(),e); }finally { try { if(in != null) { in.close(); } } catch (IOException e) { log.error(e.getMessage(),e); } // 關閉連接 FtpUtils.closeFTP(ftpClient); } } return flag; }一個頁面,這里用的ftl
Title 文件:一個簡單的controller ,里面有把MultipartFile 轉換為File 其實方法也可以直接傳輸入流,這里沒過多糾結,如果需要流的場景可以重載寫一個
package com.wzh.demo.controller;import com.wzh.config.utils.FtpManagerUtils;import com.wzh.config.utils.FtpUtils;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.stereotype.Controller;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.multipart.MultipartFile;import javax.annotation.Resource;import java.io.File;import java.io.IOException;import java.util.UUID;/** * * * * @author wzh * @version 2018-06-18 17:55 * @see [相關類/方法] (可選) **/@Controller@RequestMapping("/ftp")public class FtpController { @Autowired @Qualifier("ftpManagerUtils") private FtpManagerUtils ftpManagerUtils; @RequestMapping(value = "/upload.do",method = RequestMethod.GET) public String toFileUpload() { return "/test/fileUpload"; } @RequestMapping(value = "/upload.do", method = RequestMethod.POST) public String FileUpload(@RequestParam("file") MultipartFile file) { String suffix = FtpUtils.getSuffix(file.getOriginalFilename()); //根據自身業務做處理重命名 String newFileName = UUID.randomUUID().toString().replace("-", ""); //文件上傳 ftpManagerUtils.upLoadFile("FTP_USER_SYSTEM",file,"/file/test/",newFileName); return "/test/fileUpload"; }}去服務器查看,有uuid重命名的文件,切能正常打開
用戶頁面操作,從FTP下載文件,這個沒什么特別好說的,一般這用用在應用服務器數據庫中只存儲了用戶的文件名和基本路徑,服務器放在文件服務器上,當用戶需要下載的時候,從ftp下載文件。
文件下載工具類,這里就沒有寫特別復雜,就直接流的方式就可以了
/** * 獲取文件流 * @param ftpName ftp別名 * @param filePath ftp服務器上文件路徑 * @param out 輸出流 */ public void readFileWithOutputStream(String ftpName, String filePath, OutputStream out) { FTPClient ftpClient = linkFtp(ftpName); if(null != ftpClient) { // 綁定輸出流 FtpUtils.readFileWithOutputStream(ftpClient, filePath, out); // 關閉連接 FtpUtils.closeFTP(ftpClient); } }一個簡單的頁面
Title 文件:controller控制器
@RequestMapping(value = "/down.do",method = RequestMethod.GET) public String toFileDown() { return "test/fileDown"; } @RequestMapping(value = "/down.do", method = RequestMethod.POST) public String fileDown(HttpServletResponse response, String fileName) { try { // 設置返回編碼及瀏覽器響應類型 response.setCharacterEncoding("UTF-8"); response.setContentType("multipart/form-data;charset=UTF-8"); //獲取文件后綴名 String suffix = FtpUtils.getSuffix(fileName); //根據自身業務做處理重命名 String downName = UUID.randomUUID().toString().replace("-", "") + suffix; response.setHeader("Content-Disposition", "attachment;fileName=" + downName); //文件下載,大多數業務邏輯都是頁面傳遞文件名或ID,通過數據庫或其他文件查詢出具體文件路徑,這里為了測試,寫死 ftpManagerUtils.readFileWithOutputStream("FTP_USER_SYSTEM", "/file/test/" + fileName, response.getOutputStream()); } catch (Exception e) { e.printStackTrace(); } return "test/fileDown"; }測試一下,在代碼中也有說明,正常的下載是文件名傳遞,路徑后臺控制,這里為了測試,寫死了
點擊查詢下載成功,文件也能正常打開
這里大概就是spring 整合ftp的常用操作,寫得比較長,常見的功能都實現了,這里再次說明,很多方式沒有經過嚴格的測試,如果需要在項目中使用,需要再次測試。
總結
以上是生活随笔為你收集整理的ftpclient读取服务器文件能获得文件名文件大小0_Spring WEB工程整合使用FTP,ftp文本文件解析入库,文件上传下载的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 二十万字C/C++、嵌入式软开面试题全集
- 下一篇: 二十万字C/C++、嵌入式软开面试题全集