首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java FTP 文件上傳全流程:vsftpd 搭建、FtpClient 代碼、Nginx 靜態資源訪問

     編輯:Java 相關知識

文件上傳是業務系統高頻需求。本文記錄 Ubuntu 下 vsftpd 安裝配置(用戶、權限、被動模式)、Apache Commons Net FTPClient 上傳代碼、Nginx 反向代理靜態資源訪問全鏈路,重點解決上傳後文件權限導致 Nginx 403 的經典問題。

一、Ubuntu 搭建 vsftpd

1. 安裝與用戶創建


sudo apt-get update && sudo apt-get install vsftpd
sudo useradd -d /home/uftp -s /bin/bash -m uftp
sudo passwd uftp  # 設置密碼

2. 關鍵配置 /etc/vsftpd.conf


# 基礎設置
listen=YES
anonymous_enable=NO
local_enable=YES
write_enable=YES          # 允許上傳
local_umask=022           # 上傳文件權限 755 (777-022),解決 Nginx 403
dirmessage_enable=YES
use_localtime=YES
xferlog_enable=YES
connect_from_port_20=YES
secure_chroot_dir=/var/run/vsftpd/empty
pam_service_name=vsftpd
rsa_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
rsa_private_key_file=/etc/ssl/private/ssl-cert-snakeoil.key

# 用戶白名單(僅允許 uftp 登錄)
userlist_enable=YES
userlist_deny=NO
userlist_file=/etc/allowed_users
seccomp_sandbox=NO        # 兼容舊內核

# 被動模式(防火牆/雲服務器必配)
pasv_enable=YES
pasv_min_port=40000
pasv_max_port=40100
pasv_address=你的公網IP

3. 白名單文件


echo "uftp" | sudo tee /etc/allowed_users

4. 重啟驗證


sudo systemctl restart vsftpd
# 測試
ftp localhost
# 或使用 FileZilla/Xftp 圖形化連接

二、Java FtpClient 上傳代碼

Maven 依賴



    commons-net
    commons-net
    3.8.0


    org.apache.commons
    commons-io
    2.11.0

核心上傳工具類


public class FtpUploadUtil {
    public static boolean upload(String host, int port, String user, String pass,
                                 String remoteDir, String localFilePath, String remoteFileName) {
        FTPClient ftp = new FTPClient();
        try {
            // 1. 連接
            ftp.connect(host, port);
            int reply = ftp.getReplyCode();
            if (!FTPReply.isPositiveCompletion(reply)) {
                ftp.disconnect();
                return false;
            }

            // 2. 登錄
            if (!ftp.login(user, pass)) return false;

            // 3. 設置二進制模式、被動模式
            ftp.setFileType(FTP.BINARY_FILE_TYPE);
            ftp.enterLocalPassiveMode(); // 關鍵:客戶端發起數據連接

            // 4. 切換遠程目錄(不存在則創建)
            if (!ftp.changeWorkingDirectory(remoteDir)) {
                // 遞歸創建多級目錄
                String[] dirs = remoteDir.split("/");
                StringBuilder path = new StringBuilder();
                for (String dir : dirs) {
                    if (dir.isEmpty()) continue;
                    path.append("/").append(dir);
                    if (!ftp.changeWorkingDirectory(path.toString())) {
                        ftp.makeDirectory(path.toString());
                    }
                }
            }

            // 5. 上傳文件
            try (FileInputStream fis = new FileInputStream(localFilePath)) {
                boolean success = ftp.storeFile(remoteFileName, fis);
                return success;
            }
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        } finally {
            try {
                ftp.logout();
                ftp.disconnect();
            } catch (IOException ignored) {}
        }
    }
}

調用示例


boolean ok = FtpUploadUtil.upload(
    "192.168.148.128", 21, "uftp", "password",
    "/home/uftp/images", "D:/123.jpg", "hello.jpg");
System.out.println(ok ? "上傳成功" : "上傳失敗");

三、Nginx 靜態資源訪問配置


server {
    listen 80;
    server_name your.domain.com;

    location ~* \.(gif|jpg|jpeg|png|bmp|ico|txt|pdf)$ {
        root /home/uftp/images;        # 映射 FTP 根目錄
        expires 7d;                    # 瀏覽器緩存 7 天
        add_header Cache-Control "public";
        access_log off;
    }
}

nginx -t && nginx -s reload

驗證訪問


curl https://your.domain.com/hello.jpg
# 或瀏覽器直接打開

四、核心避坑總結

問題原因解決
上傳成功但 Nginx 返回 403vsftpd 默認 umask 077 → 文件權限 700,Nginx worker 進程無讀權限設置 local_umask=022 (文件 644/目錄 755) 或 file_open_mode=0644
上傳報 550 Permission deniedFTP 用戶無遠程目錄寫權限確保 write_enable=YES、目錄擁有者為 ftp 用戶、SELinux/AppArmor 放行
連接超時/數據連接失敗被動模式端口未開放防火牆/安全組開放 pasv_min_port-pasv_max_port 範圍,設置 pasv_address 為公網 IP
中文文件名亂碼FTP 協議默認 ISO-8859-1ftp.setControlEncoding("UTF-8"),vsftpd 配置 utf8_filesystem=YES
大文件上傳中斷網絡波動、超時設置過短ftp.setSoTimeout(0)、啟用斷點續傳 REST 指令(需服務端支持)

五、生產環境建議

  • 使用 PooledFTPClient (commons-pool2) 實現連接池,避免頻繁創建連接開銷。
  • 上傳後異步生成縮圖、水印、病毒掃描,通過消息隊列解耦。
  • 對象存儲(MinIO、S3、OSS)替代 FTP,提供更高可用性、擴展性、CDN 一體化。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved