1.業(yè)務(wù)背景
? ? ? ? 公司想實(shí)現(xiàn)文件系統(tǒng)下載,上次圖簡單就草率的寫了文件下載,這不趁著同事請(qǐng)假趕集吧這坑給填上。? ? ? ??
?
2.遇到問題
? ? ? ? 剛準(zhǔn)備開始寫,就頭疼,文件只要獲得數(shù)據(jù)輸出流就行,但是這文件夾需要維護(hù)層級(jí)關(guān)系。
? ? ? ? 前端給的是服務(wù)器的絕對(duì)地址,還得服務(wù)器的文件名對(duì)的上,不然的下載個(gè)1.doc 2.txt 3.image,另外得考慮到如果文件夾下面的文件路徑不存在會(huì)不會(huì)報(bào)錯(cuò)?
? ? ? ? ?因?yàn)槊總€(gè)文件夾的目錄的和流關(guān)聯(lián)起來 ,而且我們只知道下載的文件地址。所以在打成zip包的時(shí)候得考慮地址替換以及子文件夾創(chuàng)建的問題。
3.解決思路
? ? ? ? 解決方法很簡單,但可能一時(shí)半會(huì)給繞進(jìn)去了,都想半天了。
? ? ? ? 關(guān)于層級(jí)的問題:先去校驗(yàn)是否是文件進(jìn)行遞歸操作 沒啥難度
? ? ? ? 關(guān)于路徑的問題:使用下載路徑作為根目錄,是文件的時(shí)候?qū)⒛夸涍M(jìn)行傳遞,也無需在打成zip包在做解析文章來源:http://www.zghlxwxcb.cn/news/detail-668082.html
? ? ? ? 關(guān)于目錄的問題:需要做標(biāo)識(shí),文件放的是字節(jié)數(shù)組,文件夾放的是null,在對(duì)應(yīng)層級(jí)創(chuàng)建目錄即可。文章來源地址http://www.zghlxwxcb.cn/news/detail-668082.html
4.代碼實(shí)現(xiàn)(展現(xiàn)ftp的實(shí)現(xiàn)方式)
? ? ? ? 1.下載
/**
* 批量下載文件或者文件夾
*
* @param host 服務(wù)器地址
* @param port 端口號(hào)
* @param username 用戶名
* @param password 密碼
* @param downPaths 遠(yuǎn)程路徑
* @return void
*/
public Map<String, byte[]> batchDownloadFilesOrFolder(String host, int port, String username, String password, List<String> downPaths) throws IOException {
FTPClient ftp = getFtpClient(host, port, username, password);
Map<String, byte[]> fileBytesMap = new HashMap<>();
for (String downPath : downPaths) {
// 檢查下載路徑是否為文件夾
String rootPath = StringUtils.getFileName(downPath);
FTPFile ftpFile = ftp.mlistFile(downPath);
if (ftpFile != null && ftpFile.isDirectory()) {
fileBytesMap.put(rootPath , null);
// 如果是文件夾,則遞歸調(diào)用下載文件夾的方法
downloadDirectory(ftp, downPath, rootPath, fileBytesMap);
} else {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
if (!ftp.retrieveFile(downPath, outputStream)) {
// 文件下載失敗的處理邏輯,比如拋出異?;蛴涗浫罩? } else {
fileBytesMap.put(rootPath, outputStream.toByteArray());
}
}
}
return fileBytesMap;
}
/**
* 下載文件夾的方法
*
* @param ftp
* @param directoryPath
* @param rootPath 根目錄
* @param fileBytesMap
* @throws IOException
*/
private void downloadDirectory(FTPClient ftp, String directoryPath, String rootPath, Map<String, byte[]> fileBytesMap) throws IOException {
FTPFile[] files = ftp.listFiles(directoryPath);
for (FTPFile file : files) {
String filePath = directoryPath + "/" + file.getName();
String relativePath = rootPath + "/" + file.getName();
if (file.isFile()) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
if (!ftp.retrieveFile(filePath, outputStream)) {
// 文件下載失敗的處理邏輯,比如拋出異?;蛴涗浫罩? } else {
fileBytesMap.put(relativePath, outputStream.toByteArray());
}
} else if (file.isDirectory()) {
// 遞歸調(diào)用下載文件夾的方法
fileBytesMap.put(relativePath, null);
downloadDirectory(ftp, filePath, relativePath, fileBytesMap);
}
}
}
? ? ? ? 2.打成zip包
/**
* 將下載的流寫入zip
*
* @param bytesMap
* @param response
*/
private void downStreamWriteZip(Map<String, byte[]> bytesMap, HttpServletResponse response){
try {
// 設(shè)置響應(yīng)頭
response.setHeader("Content-Disposition", "attachment; filename=files.zip");
response.setContentType("application/zip");
// 創(chuàng)建輸出流
ServletOutputStream outputStream = response.getOutputStream();
ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream);
for (Map.Entry<String, byte[]> entry : bytesMap.entrySet()) {
String fileName = entry.getKey();
byte[] data = entry.getValue();
if (data == null) {
// 文件夾,需要?jiǎng)?chuàng)建目錄結(jié)構(gòu)
ZipEntry zipEntry = new ZipEntry(fileName + "/");
zipOutputStream.putNextEntry(zipEntry);
zipOutputStream.closeEntry();
} else {
// 文件,寫入文件數(shù)據(jù)
ZipEntry zipEntry = new ZipEntry(fileName);
zipOutputStream.putNextEntry(zipEntry);
zipOutputStream.write(data);
zipOutputStream.closeEntry();
}
}
// 關(guān)閉流
zipOutputStream.close();
outputStream.close();
} catch (IOException e) {
// 處理異常
}
}
到了這里,關(guān)于文件夾的批量下載的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!