- 💂 個人主頁: IT學習日記
- 🤟 著作權: 本文由【IT學習日記】原創、在CSDN首發、需要轉載請聯系博主
- 💬 如果文章對你有幫助、歡迎關注、點贊、收藏(一鍵三連)和訂閱專欄哦,
- 💅 想進入【技術圈子】、請查看左邊導航欄介紹!走過、路過、別錯過!
文章大綱
- 🏘? 一、前言
- 🏚? 二、專欄推薦
- 🏠 三、Window系統FTP服務器搭建
- ? 3.1、FTP服務器怎么玩
- ? 3.2、FTP(File Transfer Protocol,檔案傳輸協議)
- ? 3.3、FTP服務器
- ? 3.4、FTP服務器搭建
- ? 3.5、FTP服務器搭建出現的問題
- 🏡 四、通程序式實作FTP檔案的上傳和下載
- 💗 4.1、專案結構
- 💙 4.2、實作技術
- 💚 4.2、相關配置
- 💛 4.3、核心代碼
- 💜 4.4、執行結果
- 💝 4.5、開發程序中遇到的坑
- 🚀 六、寫在最后
| 一、前言 |
🏘? 一、前言
-
大家好,我是小誠,在開始學習之前,先給大家推薦下最近籌劃的【技術圈子】,在沒有更文的20多天里,一直在梳理之前的文章知識和學習資源,現在已經初步梳理完成,
圈子中所有資源都免費分享,資源包括但不限于面試資源、簡歷模板、年侄訓報PPT、CSDN VIP下載資源等等,感興趣者請點擊【技術圈子】,期待您的加入, -
如果文章對你有幫助,可以幫忙一鍵三連和專欄訂閱哦! -
本篇文章重點介紹:
Window環境搭建FTP服務器,JAVA程式實作FTP服務器檔案上傳、下載功能,
| 二、專欄推薦 |
🏚? 二、專欄推薦
??良心推薦: 下面的相關技術專欄還在免費分享哦,大家可以幫忙點點訂閱哦!
??面試干貨專欄
??常見開發問題專欄
??JAVA進階知識專欄
??從0到1-全面深刻理解MySQL系列專欄
| 三、Window系統Ftp服務器搭建 |
🏠 三、Window系統FTP服務器搭建
??在搭建FTP服務器之前,先跟大家介紹下什么是FTP服務器,不然怕有些小伙伴可能只是有個模糊的概念,學習要盡量知其然,知其所以然,不要一知半解,否則自己用著也不踏實,
? 3.1、FTP服務器怎么玩
??在介紹前,我們先來看看搭建完FTP服務器后能怎么玩,不然總是有些小伙伴覺的文章太長看到一半就跑路了,錯過就沒有了!
??1、上傳、下載小視頻(共享檔案),自定義權限控制,控制使用用戶,
??2、實作某些業務場景下檔案存盤和檔案下載(即檔案服務器操作),
??3、更多玩法等你開發,盡情發揮你的腦洞…
? 3.2、FTP(File Transfer Protocol,檔案傳輸協議)
??先簡單認識下FTP協議,FTP即檔案傳輸協議的簡稱,它是TCP/IP協議簇中的一員,也是Internet上最早使用的協議之一,通過它可以實作電腦與電腦間對檔案的各種操作(如檔案的增、刪、改、查、傳送等),FTP的目標是提高檔案的共享性,提供非直接使用遠程計算機,實作計算機檔案的相互操作,使存盤介質對用戶透明和可靠高效地傳送資料,
??它是基于C/S(客戶端/服務端)模型設計,作業在網路體系結構中的應用層,使用TCP進行傳輸,保證客戶與服務器之間的連接是可靠的,
??支持的連接方式:
??FTP支持Standard (PORT方式,主動方式),Passive (PASV,被動方式)兩種連接模式,連接的流程大致如下:
??1、FTP客戶端發起FTP會話,與FTP服務器建立相應的連接,在會話期間,FTP會建立控制資訊行程與資料行程兩個連接,
??2、控制行程連接的用途: 用于傳輸FTP內部命令以及命令的回應等控制資訊,無法進行資料傳輸,
??3、資料行程連接的用途: 用于客戶端與服務端之間資料的傳輸,它是全雙工的,可以支持雙向資料傳輸,當資料傳輸完成后,它就會撤銷然后回到FTP會話狀態,直到控制連接行程也取消,退出整個FTP會話,
??PORT模式:
??FTP客戶端會與服務端的TCP 21埠創建連接(控制連接),用于發送命令,當客戶端需要接收資料時,會通過這個連接向服務端發送PORT命名,PORT命令中包含了會使用什么埠來接收服務端傳輸的資料,此時,服務端會通過TCP 20埠跟FTP客戶端創建連接(資料連接)完成資料傳輸,
??Passive模式:
??FTP客戶端會與服務端的TCP 21埠創建連接(控制連接),用于發送命令,當客戶端需要接收資料時,會通過這個連接向服務端發送Pasv命名,服務器收到Pasv命令后,打開一個臨時埠(埠號大于1023小于65535)并且通知客戶端在這個埠上傳送資料的請求,客戶端連接FTP服務器此埠,然后FTP服務器將通過這個埠傳送資料,
??說明:上面FTP協議知識介紹參考百度百科:FTP協議
? 3.3、FTP服務器
??了解了FTP協議,那FTP服務器就很容易理解了,FTP服務器就是支持FTP協議的服務器,我們平常可以在電腦上安裝一個FTP工具就可實作與FTP服務器進行檔案傳輸,FTP服務器常見分為:Windows FTP服務器和Linux FTP服務器,
??我們自己的電腦也可以當做一個FTP服務器,如Windows系統就可以通過自帶的ISS管理器來搭建一個FTP服務器(本文案例就是使用這個),Linux系統最常用的借助vsftp軟體做FTP服務器搭建,
??常見的例子: 在學校里上電腦課或者電腦考試時,老師會將上課題目或者考試題目放在某個檔案夾中,讓學生訪問某個地址如:ftp://ip地址,通過這個地址每位同學看到老師共享的檔案,下載的對應的試題完成考試,
??上面例子上過電腦課的同學應該都經歷過(多么美好的學生時代),學生們訪問到的其實就是老師搭建好的FTP服務器,老師提前將共享的檔案上傳到FTP服務器,學生們可以進行下載等操作,
??啰啰嗦嗦了一大堆,下面開始進行FTP服務器搭建和上傳下載功能開發吧!
? 3.4、FTP服務器搭建
??安裝環境: Win10
??步驟一: 安裝FTP服務器支持和IIS管理平臺,
??操作步驟: 電腦 => 控制面板 => 程式和功能 => 啟用和關閉Windows功能 => Internet Infomation Services => 勾選【FTP服務器】和Web管理工具的【IIS管理控制臺】=> 點擊確定等待安裝完成

??步驟二: 打開IIS管理器
??操作步驟: 電腦 => 控制面板 => 管理工具 => Internet Infomation Services(IIS)管理器

??步驟三: 創建FTP服務器
??操作1: 在某個盤符如D盤,創建一個FTP共享檔案夾,用于FTP共享檔案存放地址
??步驟2: 右鍵IIS管理器左邊導航欄 => 添加FTP站點

??步驟3: 指定【站點名稱】和【FTP共享的檔案夾路徑】

??步驟4: 配置FTP服務器相關資訊

??步驟5: 配置FTP服務器驗證和權限資訊【注意:如果想通程序式實作上傳、下載功能,身份驗證中的基本選項需要勾選上,后面程式需要通過這個方式使用賬號和密碼登錄到FTP服務器】

??步驟5: 到這一步,一個FTP服務器就已經搭建完成了,在IIS管理器還可以對搭建好的FTP服務器進行配置管理,

??步驟6: 在同一網段的小伙伴可以通過:ftp://ftp配置的ip地址 格式訪問到FTP服務器,

? 3.5、FTP服務器搭建出現的問題
??問題一: FTP按照流程搭建完成后,在同一網段的小伙伴卻無法訪問!
??原因: 可能是開啟了防火墻攔截,需要在防火墻放行FTP服務器,
??解決: 電腦 => 控制面板 => Windows Defender 防火墻 => 允許應用通過Windows Defender 防火墻進行通信 => 勾選【FTP服務器】

| 四、通程序式實作FTP檔案的上傳和下載 |
🏡 四、通程序式實作FTP檔案的上傳和下載
??通過上面的步驟,我們完成了FTP服務器的搭建,可以手動將檔案上傳到服務器,讓在同一網段的小伙伴自由從上面下載,但是,在實際業務開發中,我們需要的是通程序式實作上傳和下載,而不是通過人為手動的方式,下面,就來看看如何實作吧,
??說明: 文章只貼出部分代碼,全部案例代碼已經上傳到Gitee,需要者可直接訪問下載(有幫助記得給個star呀):【實戰-FTP服務器搭建,實作上傳、下載】
💗 4.1、專案結構

💙 4.2、實作技術
??1、Apache下的commons-net依賴包: 它包含了一組網路實用工具和協議實作,支持的協議包括:FTP、NNTP、NTP、POP3(S)、SMTP(S)、Telnet、Whois等等,可以用它來實作檔案的上傳和下載功能,
??2、spring-boot-starter-web: web相關支持
??3、SpringBoot依賴: 快速構建JAVA專案
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>3.6</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
💚 4.2、相關配置
ftp:
client:
# ftp客戶端檔案使用的字符集
charset: GBK
server:
# ftp服務器系結ip或者域名
hostname: 127.0.0.1
# 埠
port: 21
# 連接ftp服務器的用戶名
username: user
# 密碼
password: 123456
# ftp的共享檔案路徑
workingPath: D:/share/FTPServer
# ftp服務器檔案使用的字符集(用于上傳包含中文名的檔案和下載包含中文名的檔案 - 很重要)
charset: ISO-8859-1
💛 4.3、核心代碼
??因為FTP服務器的上傳、下載都是很通用的功能,所以博主封裝成了一個工具類,有需要的小伙伴可以引入依賴和相關配置后,直接就可以使用該工具類,
??1、上傳核心代碼:
/**
* 上傳
*
* @return
*/
public boolean upload(FtpUploadParam param) {
boolean flag = false;
FTPClient ftpClient = new FTPClient();
//1 測驗連接
if (connect(ftpClient, param.getHostname(), param.getPort(), param.getUsername(), param.getPassword())) {
try {
//2 檢查作業目錄是否存在,不存在則創建
if (!ftpClient.changeWorkingDirectory(param.getWorkingPath())) {
ftpClient.makeDirectory(param.getWorkingPath());
}
// 將檔案編碼成Ftp服務器支持的編碼型別(FTP協議里面,規定檔案名編碼為iso-8859-1,所以目錄名或檔案名需要轉碼,)
String fileName = new String(param.getSaveName().getBytes(ftpClientCharset), ftpServerCharset);
// 3 上傳檔案
if (ftpClient.storeFile(fileName, param.getInputStream())) {
flag = true;
} else {
log.warn("FtpUtils uploadFile unsuccessfully!!");
}
} catch (IOException e) {
log.error("FtpUtils upload in error:{}", e);
} finally {
disconnect(ftpClient);
}
}
return flag;
}
??2、下載核心代碼:
public boolean download(FtpDownloadParam param, String downloadFileName) {
FTPClient ftpClient = new FTPClient();
FileOutputStream out = null;
//1 測驗連接
if (connect(ftpClient, param.getHostname(), param.getPort(), param.getUsername(), param.getPassword())) {
try {
File file;
String localPath = param.getDownloadPath() + param.getFileName();
out = new FileOutputStream(new File(localPath));
//2 檢查作業目錄是否存在,不存在回傳
// if (!ftpClient.changeWorkingDirectory(param.getWorkingPath())) {
// return false;
// }
/*
* 打開FTP服務器的PASS模式(不記得FTP協議支持的模式請翻到文章第一階段)
* 這個方法的意思就是每次資料連接之前,ftp client告訴ftp server開通一個埠來傳輸資料. 因為ftp
* server可能每次開啟不同的埠來傳輸資料,但是在linux上,由于安全限制,可能某些埠沒有開啟,可能出現出現阻塞
*/
ftpClient.enterLocalPassiveMode();
// 設定檔案的傳輸方式
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
// 將檔案編碼成Ftp服務器支持的編碼型別(FTP協議里面,規定檔案名編碼為iso-8859-1,所以目錄名或檔案名需要轉碼,)
// 缺少編碼轉換會導致:從FTP服務器下載下來的檔案是破損的,無法被打開
boolean b = ftpClient.retrieveFile(new String(downloadFileName
.getBytes(clientCharset), serverCharset), out);
out.flush();
} catch (IOException e) {
log.error("FtpUtils upload in error:{}", e);
return false;
} finally {
try{
if(Objects.nonNull(out)){
out.close();
}
}catch (Exception e){
log.error("FtpUtils upload in error:{}", e);
}
disconnect(ftpClient);
}
}
return true;
}
💜 4.4、執行結果
??1、演示代碼:

??2、上傳檔案到FTP服務器:

??3、從FTP服務器下載檔案到本地:

💝 4.5、開發程序中遇到的坑
??問題1、連接FTP服務器失敗:
??問題描述: 在組態檔中指定了賬號和密碼,但是卻連接失敗,
??解決方案: 經過排查,發現是在搭建FTP服務器的時候只開啟了匿名驗證,沒有開啟基本驗證(賬號和密碼登錄的方式),只需要到IIS管理器中開啟【基本驗證】即可,
??解決步驟: 電腦 => 控制面板 => 管理工具 => IIS管理器 => 搭建好的FTP服務器 => FTP身份驗證 => 開啟基本身份驗證模式,

??問題2、FTP上傳中文檔案失敗:
??問題描述: 選擇檔案名為英文的檔案上傳正常,但是選擇中文的檔案名上傳卻失敗,錯誤資訊:550-The filename, directory name, or volume label syntax is incorrect. ,
??解決方案: 經過排查,發現 FTP協議里面,規定檔案名編碼為iso-8859-1(注意:這個現在是在Windows搭建的FTP服務器出現的情況,如果是Linux環境的話,還需要查看linux默認的支持編碼而定,但是需要將上傳的檔案名編碼這個步驟是確定的),所以目錄名或檔案名需要轉碼, 所以在上傳檔案代碼處你會看到下面的對檔案解碼再編碼的代碼:

??問題3、呼叫FTPClient的切換目錄方法changeWorkingDirectory總是失敗
??原因和解決: FTP服務器搭建的時候需要我們制定共享的一個檔案路徑,當我們和FTP服務器建立連接后,默認就在這個目錄下了,如果想切換到該目錄下的子目錄,不需要寫全路徑,
??示例: 如果FTP服務器共享的檔案夾路徑為:D:/ftpserver,此時我們需要切換到ftpserver檔案夾下的子檔案demo中,正確的寫法:fTPClient.changeWorkingDirectory("demo") 而不是 fTPClient.changeWorkingDirectory(“D:/ftpserver/demo”)

??問題4、從FTP服務器下載的檔案破損,無法打開
??問題描述: 嘗試從FTP服務器下載有中文字符檔案名的檔案,成功下載到本地后卻無法正常打開,提示已經破損,
??問題原因: 原因其實和第二個問題一樣,是因為包含中文字符的檔案名下載時需要進行編碼轉換,否則下載后無法被打開,

| 五、寫在最后 |
🚀 六、寫在最后
??FTP服務器實戰專案所有代碼都已上傳到Gitee,有需要可以自取(后面會傳到CSDN免費下載),如果有幫助不要忘了star哦,Gitee專案直通車如下:【實戰-FTP服務器搭建,實作上傳、下載】
??推薦一下: 【技術圈子】中有免費面試資源、簡歷模板、年侄訓報PPT、CSDN VIP下載資源等等,期待您的加入!【不是一個人的圈子,而是技術人的圈子】
??感興趣者可以掃描下面二維碼或者查看左邊導航欄進入技術圈子,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/304514.html
標籤:java
上一篇:SSA
下一篇:圖文并茂-----看懂堆排序
