欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java操作FTP實(shí)現(xiàn)上傳下載功能

 更新時(shí)間:2022年11月01日 11:31:59   作者:野生java研究僧  
這篇文章主要為大家詳細(xì)介紹了Java如何通過(guò)操作FTP實(shí)現(xiàn)上傳下載的功能,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Java有一定幫助,需要的可以參考一下

FTP簡(jiǎn)介

文件傳輸協(xié)議(File Transfer Protocol,F(xiàn)TP)是用于在網(wǎng)絡(luò)上進(jìn)行文件傳輸?shù)囊惶讟?biāo)準(zhǔn)協(xié)議,它工作在 OSI 模型的第七層,TCP 模型的第四層, 即應(yīng)用層, 使用 TCP 傳輸而不是 UDP, 客戶在和服務(wù)器建立連接前要經(jīng)過(guò)一個(gè)“三次握手”的過(guò)程, 保證客戶與服務(wù)器之間的連接是可靠的, 而且是面向連接, 為數(shù)據(jù)傳輸提供可靠保證。

FTP也是一個(gè)應(yīng)用程序,基于不同的操作系統(tǒng)有不同的FTP應(yīng)用程序,而所有這些應(yīng)用程序都遵守同一種協(xié)議以傳輸文件。可以使用FTP進(jìn)行下載和上傳。

文件傳送協(xié)議FTP(File Transfer Protocol)是Internet上使用比較廣泛的文件傳送協(xié)議。FTP提供交互式的訪問,允許客戶指明文件的類型與格式,并允許文件具有存取權(quán)限。FTP屏蔽了各種計(jì)算機(jī)系統(tǒng)的細(xì)節(jié),因此適用于在異構(gòu)網(wǎng)絡(luò)中任意計(jì)算機(jī)之間傳送文件。它的基本應(yīng)用就是將文件從一臺(tái)計(jì)算機(jī)復(fù)制到另一臺(tái)計(jì)算機(jī)中。它要存取一個(gè)文件,就必須先獲得一個(gè)本地文件的副本,如果修改文件,也只能對(duì)文件的副本進(jìn)行修改,然后再將修改后的文件副本傳回到原節(jié)點(diǎn)。

您只要記住幾個(gè)關(guān)鍵詞:交互式、存取權(quán)限和副本。

簡(jiǎn)單文件傳送協(xié)議TFTP(Trivial File Transfer Protocol)是一個(gè)小而易于實(shí)現(xiàn)的文件傳送協(xié)議。TFTP是基于UDP數(shù)據(jù)報(bào),需要有自己的差錯(cuò)改正措施。TFTP只支持文件傳輸,不支持交互,沒有龐大的命令集。也沒有目錄列表功能,以及不能對(duì)用戶進(jìn)行身份鑒別。但它的代碼所占內(nèi)存較小,不需要硬盤就可以固化TFTP代碼,很適合較小的計(jì)算機(jī)和特殊用途的設(shè)備。

您會(huì)發(fā)現(xiàn)TFTP和FTP一個(gè)主要的區(qū)別就是它沒有交互式,且不進(jìn)行身份驗(yàn)證。

FTP的客戶可以是任意平臺(tái)

FTP標(biāo)準(zhǔn)端口:

  • 20 數(shù)據(jù)接口
  • 21 指令接口

FTP架構(gòu)

FTP監(jiān)聽于TCP的21號(hào)端口,是一種C/S架構(gòu)的應(yīng)用程序。在Linux中常用的服務(wù)端軟件和客戶端軟件一般如下表所示:

FTP數(shù)據(jù)連接模式

FTP有2種數(shù)據(jù)連接模式:命令連接和數(shù)據(jù)連接

  • 命令連接:是指文件管理類命令,始終在線的持久性連接,直到用戶退出登錄為止(可以簡(jiǎn)單的理解為建立連接)
  • 數(shù)據(jù)連接:是指數(shù)據(jù)傳輸,按需創(chuàng)建及關(guān)閉的連接(可以簡(jiǎn)單的理解為傳輸數(shù)據(jù))

數(shù)據(jù)連接需要關(guān)注的點(diǎn)有:

1.數(shù)據(jù)傳輸格式

  • 文件傳輸
  • 二進(jìn)制傳輸

2.數(shù)據(jù)傳輸模式

  • 主動(dòng)模式:由服務(wù)器端創(chuàng)建數(shù)據(jù)連接
  • 被動(dòng)模式:由客戶端創(chuàng)建數(shù)據(jù)連接

兩種數(shù)據(jù)傳輸模式的建立過(guò)程:

1.主動(dòng)模式

命令連接(建立連接通道)

Client端以一個(gè)1024以上的隨機(jī)端口(端口號(hào)大于1023小于65535)來(lái)連接Server端的21號(hào)端口

數(shù)據(jù)連接(傳輸數(shù)據(jù))

Server端以20號(hào)端口去連接Client創(chuàng)建命令連接時(shí)使用的隨機(jī)端口+1的端口

示例:

命令連接:Client(9527)–> Server(21),數(shù)據(jù)連接:Server(20/tcp) --> Client(9527+1)

2.被動(dòng)模式

命令連接

Client以一個(gè)1024以上的隨機(jī)端口號(hào)(端口號(hào)大于1023小于65535)來(lái)連接Server端的21號(hào)端口,命令連接建立完畢后,Server端會(huì)告知Client端用于創(chuàng)建數(shù)據(jù)連接的隨機(jī)端口號(hào)(端口號(hào)大于1023小于65535)

數(shù)據(jù)連接

Client以創(chuàng)建命令連接時(shí)使用的隨機(jī)端口號(hào)+1去連服務(wù)器端通過(guò)命令連接告知自己的一個(gè)隨機(jī)端口號(hào)來(lái)創(chuàng)建數(shù)據(jù)連接

示例:

命令連接:Client(9527) --> Server(21),數(shù)據(jù)連接:Client(9527+1) --> Server(隨機(jī)端口)

注意:

主動(dòng)模式存在弊端,因?yàn)榭蛻舳说亩丝谑请S機(jī)的,客戶端如果開了防火墻,則服務(wù)器端去連客戶端創(chuàng)建數(shù)據(jù)連接時(shí)可能會(huì)被拒絕

用戶認(rèn)證

Ftp的用戶認(rèn)證主要有三種:

1.虛擬用戶:僅用于訪問某特定服務(wù)中的資源

虛擬用戶通過(guò)ftp訪問的資源位置為給虛擬用戶指定的映射成為的系統(tǒng)用戶的家目錄

2.系統(tǒng)用戶:可以登錄系統(tǒng)的真實(shí)用戶(出于對(duì)安全性的考慮,這種認(rèn)證很少使用)

系統(tǒng)用戶通過(guò)ftp訪問的資源位置為用戶的家目錄

3.匿名用戶

匿名用戶(映射為ftp用戶)的共享資源位置是/var/ftp

服務(wù)端

  • /etc/pam.d/vsftpd #vsftpd用戶認(rèn)證配置文件
  • /etc/vsftpd/ #配置文件目錄
  • /etc/vsftpd/vsftpd.conf #主配置文件
  • vsftpd常見的配置參數(shù)

客戶端

lftp工具 支持指定用戶名和密碼登錄

Vsftp安裝與配置

在linux環(huán)境下,使用最多的FTP服務(wù)端軟件就是Vsftpd!

安裝Vsftpd,運(yùn)行一下命令需要在root用戶下進(jìn)行!

yum install vsftpd 安裝
yum remove vsftpd 卸載

啟動(dòng)服務(wù)

啟動(dòng)服務(wù) service vsftpd start 或者 systemctl start vsftpd.service  

重啟服務(wù) systemctl restart vsftpd.service 

停止服務(wù) systemctl stop vsftpd.service 

設(shè)置開機(jī)自啟動(dòng)  systemctl enable vsftpd.service    

配置文件說(shuō)明

/etc/vsftpd/vsftpd.conf 這個(gè)文件是vsftpd服務(wù)的核心配置文件!

我們?cè)谛薷呐渲梦募臅r(shí)候,最好先備份一份!

cp /etc/vsftpd/vsftpd.conf /etc/vsftpd/vsftpd.conf.bak

/etc/vsftpd/ftpusers這個(gè)文件是禁止使用vsftpd的用戶列表文件。記錄不允許訪問FTP服務(wù)器的用戶名單,管理員可以把一些對(duì)系統(tǒng)安全有威脅的用戶賬號(hào)記錄在此文件中,以免用戶從FTP登錄后獲得大于上傳下載操作的權(quán)利,而對(duì)系統(tǒng)造成損壞。

/etc/vsftpd/user_list這個(gè)文件禁止或允許使用vsftpd的用戶列表文件。這個(gè)文件中指定的用戶缺省情況(即在/etc/vsftpd/vsftpd.conf中設(shè)置userlist_deny=YES)下也不能訪問FTP服務(wù)器,在設(shè)置了userlist_deny=NO時(shí),僅允許user_list中指定的用戶訪問FTP服務(wù)器。

注意配置文件中的值一定不要有空格

# Example config file /etc/vsftpd/vsftpd.conf
#
#
# 禁止匿名登錄
anonymous_enable=NO
# 是否允許本地用戶(即linux系統(tǒng)中的用戶帳號(hào))登錄FTP服務(wù)器,默認(rèn)設(shè)置為YES允許
# 本地用戶登錄后會(huì)進(jìn)入用戶主目錄,而匿名用戶登錄后進(jìn)入匿名用戶的下載目錄/var/ftp/pub
# 若只允許匿名用戶訪問,前面加上 #注釋掉即可阻止本地用戶訪問FTP服務(wù)器
local_enable=YES
#
# 是否允許本地用戶對(duì)FTP服務(wù)器文件具有寫權(quán)限,默認(rèn)設(shè)置為YES允許
write_enable=YES
#
# 掩碼,本地用戶默認(rèn)掩碼為077
# 你可以設(shè)置本地用戶的文件掩碼為缺省022,也可根據(jù)個(gè)人喜好將其設(shè)置為其他值
local_umask=022
#
# 是否允許匿名用戶上傳文件,須將全局的write_enable=YES。默認(rèn)為YES
#anon_upload_enable=YES
#
#是否允許匿名用戶創(chuàng)建新文件夾
#anon_mkdir_write_enable=YES

# 是否激活目錄歡迎信息功能
# 當(dāng)用戶用CMD模式首次訪問服務(wù)器上某個(gè)目錄時(shí),F(xiàn)TP服務(wù)器將顯示歡迎信息
# 默認(rèn)情況下,歡迎信息是通過(guò)該目錄下的.message文件獲得的
# 此文件保存自定義的歡迎信息,由用戶自己建立
dirmessage_enable=YES
#
# 是否讓系統(tǒng)自動(dòng)維護(hù)上傳和下載的日志文件
# 默認(rèn)情況該日志文件為/var/log/vsftpd.log,也可以通過(guò)下面的xferlog_file選項(xiàng)對(duì)其進(jìn)行設(shè)定
# 默認(rèn)值為NO
xferlog_enable=YES
#
# 是否設(shè)定FTP服務(wù)器將啟用FTP數(shù)據(jù)端口的連接請(qǐng)求
# ftp-data數(shù)據(jù)傳輸,21為連接控制端口
connect_from_port_20=YES
#
# 設(shè)定是否允許改變上傳文件的屬主,與下面一個(gè)設(shè)定項(xiàng)配合使用
# 注意,不推薦使用root用戶上傳文件
#chown_uploads=YES
# 設(shè)置想要改變的上傳文件的屬主,如果需要,則輸入一個(gè)系統(tǒng)用戶名
# 可以把上傳的文件都改成root屬主。whoever:任何人
#chown_username=whoever
#
# 設(shè)定系統(tǒng)維護(hù)記錄FTP服務(wù)器上傳和下載情況的日志文件
#xferlog_file=/var/log/xferlog
#
#如果你想,你可以有一個(gè)標(biāo)準(zhǔn)的ftpd xferlog格式的日志文件。
#注意默認(rèn)的日志文件位置是/var/log/xferlog。
xferlog_std_format=YES
#
#您可以更改默認(rèn)值,以使空閑會(huì)話超時(shí)。
#idle_session_timeout=600
#
# #您可以更改數(shù)據(jù)連接超時(shí)的默認(rèn)值。
#data_connection_timeout=120
#
#運(yùn)行vsftpd需要的非特權(quán)系統(tǒng)用戶,缺省是nobody
#nopriv_user=ftpsecure
#
# 是否識(shí)別異步ABOR請(qǐng)求。
# 如果FTP client會(huì)下達(dá)“async ABOR”這個(gè)指令時(shí),這個(gè)設(shè)定才需要啟用
# 而一般此設(shè)定并不安全,所以通常將其取消
#async_abor_enable=YES
#
# 是否以ASCII方式傳輸數(shù)據(jù)。默認(rèn)情況下,服務(wù)器會(huì)忽略ASCII方式的請(qǐng)求。
# 啟用此選項(xiàng)將允許服務(wù)器以ASCII方式傳輸數(shù)據(jù)
# 不過(guò),這樣可能會(huì)導(dǎo)致由"SIZE /big/file"方式引起的DoS攻擊
#ascii_upload_enable=YES
#ascii_download_enable=YES

# 登錄FTP服務(wù)器時(shí)顯示的歡迎信息
# 如有需要,可在更改目錄歡迎信息的目錄下創(chuàng)建名為.message的文件,并寫入歡迎信息保存后
#ftpd_banner=Welcome to blah FTP service.

# 黑名單設(shè)置。如果很討厭某些email address,就可以使用此設(shè)定來(lái)取消他的登錄權(quán)限
# 可以將某些特殊的email address抵擋住。
#deny_email_enable=YES

# 當(dāng)上面的deny_email_enable=YES時(shí),可以利用這個(gè)設(shè)定項(xiàng)來(lái)規(guī)定哪些郵件地址不可登錄vsftpd服務(wù)器
# 此文件需用戶自己創(chuàng)建,一行一個(gè)email address即可
#banned_email_file=/etc/vsftpd/banned_emails

# You may specify an explicit list of local users to chroot() to their home
# directory. If chroot_local_user is YES, then this list becomes a list of
# users to NOT chroot().
# (Warning! chroot'ing can be very dangerous. If using chroot, make sure that
# the user does not have write access to the top level directory within the
# chroot)
chroot_local_user=YES

#  允許 chroot 用戶具備寫權(quán)限
allow_writeable_chroot=YES
#當(dāng)chroot_list_enable=YES,chroot_local_user=YES時(shí),在/etc/vsftpd.chroot_list文件中列出的用戶,可以切換到其他目錄;未在文件中列出的用戶,不能切換到其他目錄。
#當(dāng)chroot_list_enable=YES,chroot_local_user=NO時(shí),在/etc/vsftpd.chroot_list文件中列出的用戶,不能切換到其他目錄;未在文件中列出的用戶,可以切換到其他目錄。
#當(dāng)chroot_list_enable=NO,chroot_local_user=YES時(shí),所有的用戶均不能切換到其他目錄。
#當(dāng)chroot_list_enable=NO,chroot_local_user=NO時(shí),所有的用戶均可以切換到其他目錄。
chroot_list_enable=YES

# 被列入此文件的用戶,在登錄后將不能切換到自己目錄以外的其他目錄
# 從而有利于FTP服務(wù)器的安全管理和隱私保護(hù)。此文件需自己建立
#chroot_list_file=/etc/vsftpd/chroot_list
#
# 是否允許遞歸查詢。默認(rèn)為關(guān)閉,以防止遠(yuǎn)程用戶造成過(guò)量的I/O
#ls_recurse_enable=YES
#
# 是否允許監(jiān)聽。
# 如果設(shè)置為YES,則vsftpd將以獨(dú)立模式運(yùn)行,由vsftpd自己監(jiān)聽和處理IPv4端口的連接請(qǐng)求
listen=YES
#
# 設(shè)定是否支持IPV6。如要同時(shí)監(jiān)聽I(yíng)Pv4和IPv6端口,
# 則必須運(yùn)行兩套vsftpd,采用兩套配置文件
# 同時(shí)確保其中有一個(gè)監(jiān)聽選項(xiàng)是被注釋掉的
# listen_ipv6=NO

# 設(shè)置是否阻扯user_list文件中的用戶登錄FTP服務(wù)器,默認(rèn)為YES
#userlist_deny=YES/NO

# 設(shè)置PAM外掛模塊提供的認(rèn)證服務(wù)所使用的配置文件名,即/etc/pam.d/vsftpd文件
# 此文件中file=/etc/vsftpd/ftpusers字段,說(shuō)明了PAM模塊能抵擋的帳號(hào)內(nèi)容來(lái)自文件/etc/vsftpd/ftpusers中
pam_service_name=vsftpd

# 是否允許ftpusers文件中的用戶登錄FTP服務(wù)器,默認(rèn)為NO
# 若此項(xiàng)設(shè)為YES,則user_list文件中的用戶允許登錄FTP服務(wù)器
# 而如果同時(shí)設(shè)置了userlist_deny=YES,則user_list文件中的用戶將不允許登錄FTP服務(wù)器,甚至連輸入密碼提示信息都沒有
userlist_enable=YES
# 是否使用tcp_wrappers作為主機(jī)訪問控制方式。
# tcp_wrappers可以實(shí)現(xiàn)linux系統(tǒng)中網(wǎng)絡(luò)服務(wù)的基于主機(jī)地址的訪問控制
# 在/etc目錄中的hosts.allow和hosts.deny兩個(gè)文件用于設(shè)置tcp_wrappers的訪問控制
# 前者設(shè)置允許訪問記錄,后者設(shè)置拒絕訪問記錄。
# 如想限制某些主機(jī)對(duì)FTP服務(wù)器192.168.57.2的匿名訪問,編緝/etc/hosts.allow文件,如在下面增加兩行命令:
# vsftpd:192.168.57.1:DENY 和vsftpd:192.168.57.9:DENY
# 表明限制IP為192.168.57.1/192.168.57.9主機(jī)訪問IP為192.168.57.2的FTP服務(wù)器
# 此時(shí)FTP服務(wù)器雖可以PING通,但無(wú)法連接
tcp_wrappers=YES

#開啟被動(dòng)模式
pasv_enable=YES
# 傳輸文件的端口范圍,如果是云服務(wù)器記得開放端口,linux服務(wù)器本身也要開放端口
pasv_min_port=9000
pasv_max_port=9005

傳輸模式配置

開啟被動(dòng)模式:

connect_from_port_20=NO(默認(rèn)為YES) #設(shè)置是否允許主動(dòng)模式
pasv_enable=YES(默認(rèn)為YES) #設(shè)置是否允許被動(dòng)模式
pasv_min_port=50000(default:0(use any port))
pasv_max_port=60000(default:0(use any port))

開啟主動(dòng)模式:

connect_from_port_20=YES
pasv_enable=NO

系統(tǒng)用戶配置

linux創(chuàng)建用戶:

useradd -d /home/ftp/compass -s /sbin/nologin  compass
passwd compass

為虛擬用戶創(chuàng)建家目錄

mkdir -p /home/ftp/compass

設(shè)置權(quán)限

chown -R compass:compass /home/ftp/compass

配置selinux允許ftp訪問home和外網(wǎng)訪問

[root@master ~]# setsebool -P allow_ftpd_full_access on
[root@master ~]# setsebool -P tftp_home_dir on

重啟vsftpd服務(wù)

[root@master ~]# systemctl restart vsftpd

無(wú)法登錄的情況 在/etc/vsftpd/vsftpd.conf配置文件中添加了以下兩句

    chroot_local_user=YES  #原本就有,取掉注釋就好
    allow_writeable_chroot=YES   #添加
    chown compass:compass -R /home/ftp/compass

java操作ftp文件服務(wù)器

有時(shí)候,我們需要接收用戶上傳的文件存儲(chǔ)到服務(wù)器,然后保存起來(lái),下次用戶可以直接下載,或者是保存為檔案,我這里提供三個(gè)方法,一個(gè)是上傳文件到ftp,還有就是從ftp下載文件,還有就是刪除ftp服務(wù)器刪的文件

1.引入依賴

       <!--    ftp上傳下載-->
        <dependency>
            <groupId>commons-net</groupId>
            <artifactId>commons-net</artifactId>
            <version>3.7</version>
        </dependency>

2.提供接口

import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.io.OutputStream;

/**
 * ftp文件服務(wù)器操作接口
 *
 * @author compass
 * @date 2022/10/19 15:00
 * @since 1.0.0
 **/
public interface FtpService {

    /**
     * 上傳文件到ftp
     *
     * @param inputStream 輸入流
     * @param fileName    新的文件名,包含拓展名
     * @param filePath    保存路徑
     * @return
     * @author compass
     */
    Boolean uploadFile(InputStream inputStream, String fileName, String filePath);

    /**
     * 下載ftp文件,直接轉(zhuǎn)到輸出流
     * @author compass
     * @param ftpFilePath
     * @author compass
     */
    byte[] downloadFileBytes(String ftpFilePath, HttpServletResponse response);

    /**
     * 刪除ftp文件
     * @author compass
     * @param ftpFilePath ftp下文件路徑,根目錄開始
     * @return
     */
    Boolean deleteFile(String ftpFilePath);
}

3.對(duì)提供操作ftp接口進(jìn)行實(shí)現(xiàn)

/**
 * @author compass
 * @date 2022-10-19
 * @since 1.0
 **/

import java.io.*;

import compass.token.pocket.com.common.AjaxResult;
import compass.token.pocket.com.entity.FtpInstanceEntity;
import compass.token.pocket.com.service.FtpService;
import compass.token.pocket.com.utils.ResponseUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;

@Slf4j
@Service
public class FtpServiceImpl implements FtpService {

    @Resource
    FtpInstanceEntity ftpInstanceEntity;

    /**
     * 上傳文件到ftp
     *
     * @param inputStream 輸入流
     * @param fileName    新的文件名,包含拓展名
     * @param filePath    保存路徑
     * @return
     * @author compass
     */
    @Override
    public Boolean uploadFile(InputStream inputStream, String fileName, String filePath) {
        // 定義保存結(jié)果
        boolean isSuccess = false;
        // 初始化連接
        FTPClient ftp = connectFtpServer();
        if (ftp != null) {
            try {
                // 設(shè)置文件傳輸模式為二進(jìn)制,可以保證傳輸?shù)膬?nèi)容不會(huì)被改變
                ftp.setFileType(FTP.BINARY_FILE_TYPE);
                //注:上傳文件都為0字節(jié),設(shè)置為被動(dòng)模式即可
                ftp.enterLocalPassiveMode();
                // 跳轉(zhuǎn)到指定路徑,逐級(jí)跳轉(zhuǎn),不存在的話就創(chuàng)建再進(jìn)入
                toPathOrCreateDir(ftp, filePath);
                // 上傳文件 參數(shù):上傳后的文件名,輸入流,,返回Boolean類型,上傳成功返回true
                isSuccess = ftp.storeFile(fileName, inputStream);
                // 關(guān)閉輸入流
                inputStream.close();
                // 退出ftp
                ftp.logout();
            } catch (IOException e) {
                log.error(e.toString());
            } finally {
                if (ftp.isConnected()) {
                    try {
                        // 斷開ftp的連接
                        ftp.disconnect();
                    } catch (IOException ioe) {
                        log.error(ioe.toString());
                    }
                }
            }
        }
        return isSuccess;
    }

    /**
     * 下載ftp文件,直接轉(zhuǎn)到輸出流
     *
     * @param ftpFilePath
     * @author compass
     */
    @Override
    public byte[] downloadFileBytes(String ftpFilePath , HttpServletResponse response) {
        FTPClient ftp = connectFtpServer();
        try {
            ByteArrayOutputStream stream = new ByteArrayOutputStream();
            ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
            ftp.enterLocalPassiveMode();
            boolean retrieveFile = ftp.retrieveFile(ftpFilePath, stream);
            if (!retrieveFile){
                throw new RuntimeException("FTP文件下載失敗");
            }
            ftp.logout();
            return stream.toByteArray();
        } catch (Exception e) {
            log.error("FTP文件下載失敗!" + e.toString());
            ResponseUtil.response(response,AjaxResult.businessError(e.getMessage(), "-1"));
            throw new RuntimeException(e.getMessage());
        } finally {
            if (ftp.isConnected()) {
                try {
                    ftp.disconnect();
                } catch (IOException ioe) {
                    log.error(ioe.toString());
                }
            }

        }
    }

    /**
     * 刪除ftp文件
     * @param ftpFilePath 文件路徑
     * @return java.lang.Boolean
     * @author compass
     * @date 2022/10/19 18:35
     * @since 1.0.0
     **/
    @Override
    public Boolean deleteFile(String ftpFilePath ) {
        FTPClient ftp = connectFtpServer();
        boolean result = false;
        try {
            result = ftp.deleteFile(ftpFilePath);
            ftp.logout();
            return result;
        } catch (Exception e) {
            log.error("FTP文件刪除失??!" + e.toString());
        } finally {
            if (ftp.isConnected()) {
                try {
                    ftp.disconnect();
                } catch (IOException ioe) {
                    log.error(ioe.toString());
                }
            }
        }
        return result;
    }

    /**
     * 創(chuàng)建FTPClient對(duì)象
     *
     * @return org.apache.commons.net.ftp.FTPClient
     * @author compass
     * @date 2022/10/19 18:35
     * @since 1.0.0
     **/
    private FTPClient connectFtpServer() {
        // 創(chuàng)建FTPClient對(duì)象(對(duì)于連接ftp服務(wù)器,以及上傳和上傳都必須要用到一個(gè)對(duì)象)
        FTPClient ftpClient = new FTPClient();
        // 設(shè)置連接超時(shí)時(shí)間
        ftpClient.setConnectTimeout(1000 * 10);
        // 設(shè)置ftp字符集
        ftpClient.setControlEncoding("utf-8");
        // 設(shè)置被動(dòng)模式,文件傳輸端口設(shè)置,否則文件上傳不成功,也不報(bào)錯(cuò)
        ftpClient.enterLocalPassiveMode();
        try {
            // 定義返回的狀態(tài)碼
            int replyCode;
            // 連接ftp(當(dāng)前項(xiàng)目所部署的服務(wù)器和ftp服務(wù)器之間可以相互通訊,表示連接成功)
            ftpClient.connect(ftpInstanceEntity.getHost());
            // 輸入賬號(hào)和密碼進(jìn)行登錄
            ftpClient.login(ftpInstanceEntity.getUsername(), ftpInstanceEntity.getPassword());
            // 接受狀態(tài)碼(如果成功,返回230,如果失敗返回503)
            replyCode = ftpClient.getReplyCode();
            // 根據(jù)狀態(tài)碼檢測(cè)ftp的連接,調(diào)用isPositiveCompletion(reply)-->如果連接成功返回true,否則返回false
            if (!FTPReply.isPositiveCompletion(replyCode)) {
                log.info("connect ftp {} failed", ftpInstanceEntity.getHost());
                // 說(shuō)明連接失敗,需要斷開連接
                ftpClient.disconnect();
                throw new RuntimeException(String.format("connect ftp %s failed", ftpInstanceEntity.getHost()));
            }
            log.info("連接狀態(tài)碼:" + replyCode);
        } catch (IOException e) {
            log.error("connect fail:" + e.toString());
            throw new RuntimeException(String.format("connect ftp %s error", ftpInstanceEntity.getHost()));
        }
        return ftpClient;
    }

    /**
     * 跳轉(zhuǎn)到指定路徑 不存在就創(chuàng)建
     *
     * @param ftp      操作ftp對(duì)象
     * @param filePath 文件路徑
     * @return void
     * @author compass
     * @date 2022/10/19 15:05
     * @since 1.0.0
     **/
    private void toPathOrCreateDir(FTPClient ftp, String filePath) throws IOException {
        String[] dirs = filePath.split("/");
        for (String dir : dirs) {
            if (StringUtils.isEmpty(dir)) {
                continue;
            }
            if (!ftp.changeWorkingDirectory(dir)) {
                ftp.makeDirectory(dir);
                ftp.changeWorkingDirectory(dir);
            }
        }
    }

}

4.配置ftp相關(guān)參數(shù)

在配置文件中配置連接ftp服務(wù)器的配置

ftp:
  #ftp服務(wù)器的地址
  host: 127.0.0.1
  #ftp服務(wù)器的端口號(hào)(連接端口號(hào))
  port: 21
  #ftp的用戶名
  username: compass
  #ftp的密碼
  password: 6317738ef8324199a24602308f3a9a18
  #ftp上傳的根目錄
  basePath: /home/ftp/compass
  #回顯地址
  httpPath: ftp://127.0.0.1

然后將配置文件的內(nèi)容讀取到一個(gè)bean里面

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

@Data
@Configuration
@ConfigurationProperties(prefix = "ftp")
public class FtpInstanceEntity {
    /**
     * ftp服務(wù)器的地址
     */
    private String host;
    /**
     * ftp服務(wù)器的端口號(hào)(連接端口號(hào))
     */
    private String port;
    /**
     * ftp的用戶名
     */
    private String username;
    /**
     * ftp的密碼
     */
    private String password;
    /**
     * ftp上傳的根目錄
     */
    private String basePath;
    /**
     * 回顯地址
     */
    private String httpPath;

}

5.寫測(cè)試controller

package compass.token.pocket.com.controller;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import compass.token.pocket.com.common.AjaxResult;
import compass.token.pocket.com.entity.FtpInstanceEntity;
import compass.token.pocket.com.service.FtpService;
import compass.token.pocket.com.utils.FileUtils;
import compass.token.pocket.com.utils.ResponseUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 文件測(cè)試控制器
 * @author compass
 * @date 2022/10/27 22:41
 * @since 1.0.0
 **/
@Slf4j
@RestController
@RequestMapping("/fileTestController")
public class FileTestController {

    @Resource
    private FtpService ftpService;

    @Resource
    FtpInstanceEntity ftpInstanceEntity;


    /**
     * ftp服務(wù)器文件上傳
     * @param file 需要上傳的文件
     * @return compass.token.pocket.com.common.AjaxResult<java.lang.String>
     * @author compass
     * @date 2022/10/19 14:51
     * @since 1.0.0
     **/
    @PostMapping(value = "/pdfUpload")
    public AjaxResult<String> pdfUpload(@RequestParam("file") MultipartFile file) {
        try {
            String fileDir = DateUtil.format(new Date(), "yyyy-MM-dd");
            boolean upload = ftpService.uploadFile(file.getInputStream(), file.getOriginalFilename(), fileDir);
            if (upload) {
                String savePath = ftpInstanceEntity.getBasePath() + "/" + fileDir + "/" + file.getOriginalFilename();
                return AjaxResult.success("上傳成功", savePath);
            } else {
                return new AjaxResult<>("file upload error");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return new AjaxResult<>("file upload error");
    }

    /**
     * ftp服務(wù)器文件下載
     * @param ftpPath 需要下載的文件路徑
     * @return compass.token.pocket.com.common.AjaxResult<java.lang.String>
     * @author compass
     * @date 2022/10/19 14:51
     * @since 1.0.0
     **/
    @GetMapping(value = "/pdfDownload", produces = "application/octet-stream")
    public void downloadFile(@RequestParam("ftpPath") String ftpPath, HttpServletRequest request, HttpServletResponse response) {
        String userAgent = request.getHeader("User-Agent");
        String fileName = ftpPath.substring(ftpPath.lastIndexOf('/') + 1);
        try {
            if (userAgent.contains("MSIE") || userAgent.contains("Trident")) {
                //IE瀏覽器處理
                fileName = URLEncoder.encode(fileName, "UTF-8");
            } else {
                // 非IE瀏覽器的處理:
                fileName = new String(fileName.getBytes("UTF-8"), "ISO-8859-1");
            }
            response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
            response.setContentType("application/octet-stream; charset=UTF-8");
            byte[] bytes = ftpService.downloadFileBytes( ftpPath,response);
            ServletOutputStream outputStream = response.getOutputStream();
            outputStream.write(bytes);
            outputStream.flush();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * ftp服務(wù)器文件刪除
     * @param ftpPath 需要?jiǎng)h除的文件路徑
     * @return compass.token.pocket.com.common.AjaxResult<java.lang.Boolean>
     * @author compass
     * @date 2022/10/19 14:51
     * @since 1.0.0
     **/
    @PostMapping("ftpDeleteFile")
    public AjaxResult<Boolean> ftpDeleteFile(@RequestParam("ftpPath") String ftpPath){
        Boolean isSuccess = ftpService.deleteFile(ftpPath);
        if (isSuccess){
             return  AjaxResult.success("刪除成功", true);
        }else {
            return  AjaxResult.businessError("刪除失敗", false);
        }

    }

}

到這里操作ftp文件服務(wù)器的基本操作差不多結(jié)束了,講的不是特別詳細(xì),但是基本來(lái)說(shuō),夠用,如果遇到不能解決的問題請(qǐng)自行百度。

以上就是Java操作FTP實(shí)現(xiàn)上傳下載功能的詳細(xì)內(nèi)容,更多關(guān)于Java FTP上傳下載的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java加密 消息摘要算法SHA實(shí)現(xiàn)詳解

    Java加密 消息摘要算法SHA實(shí)現(xiàn)詳解

    這篇文章主要介紹了Java加密 消息摘要算法SHA實(shí)現(xiàn)詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-07-07
  • springboot如何使用MybatisPlus

    springboot如何使用MybatisPlus

    MyBatisPlus是一個(gè)強(qiáng)大的數(shù)據(jù)庫(kù)操作框架,其代碼生成器可以快速生成實(shí)體類、映射文件等,本文介紹了如何導(dǎo)入MyBatisPlus相關(guān)依賴,創(chuàng)建代碼生成器,并配置數(shù)據(jù)庫(kù)信息以逆向生成代碼,感興趣的朋友跟隨小編一起看看吧
    2024-09-09
  • SpringBoot升級(jí)指定jackson版本的問題

    SpringBoot升級(jí)指定jackson版本的問題

    這篇文章主要介紹了SpringBoot升級(jí)指定jackson版本,本文給大家分享了漏洞通告及修改Springboot中jackson版本的問題,需要的朋友可以參考下
    2022-08-08
  • Spring Cloud升級(jí)最新Finchley版本的所有坑

    Spring Cloud升級(jí)最新Finchley版本的所有坑

    這篇文章主要介紹了Spring Cloud升級(jí)最新Finchley版本的所有坑,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-08-08
  • Java將byte[]轉(zhuǎn)圖片存儲(chǔ)到本地的案例

    Java將byte[]轉(zhuǎn)圖片存儲(chǔ)到本地的案例

    這篇文章主要介紹了Java將byte[]轉(zhuǎn)圖片存儲(chǔ)到本地的案例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-10-10
  • mybatis?實(shí)現(xiàn)多層級(jí)collection嵌套

    mybatis?實(shí)現(xiàn)多層級(jí)collection嵌套

    這篇文章主要介紹了mybatis?實(shí)現(xiàn)多層級(jí)collection嵌套,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • Java如何使用poi導(dǎo)入導(dǎo)出excel工具類

    Java如何使用poi導(dǎo)入導(dǎo)出excel工具類

    這篇文章主要介紹了Java如何使用poi導(dǎo)入導(dǎo)出excel工具類問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-06-06
  • Java異常詳解_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    Java異常詳解_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    異常是Java語(yǔ)言中的一部分,它代表程序中由各種原因引起的“不正?!币蛩?。下面通過(guò)本文給大家介紹java異常的相關(guān)知識(shí),感興趣的朋友一起看看吧
    2017-06-06
  • 淺析Java隨機(jī)數(shù)與定時(shí)器

    淺析Java隨機(jī)數(shù)與定時(shí)器

    本篇文章給大家分析了Java隨機(jī)數(shù)與定時(shí)器的實(shí)現(xiàn)原理以及代碼分享,有需要的讀者參考下吧。
    2018-02-02
  • 解讀tk.mybatis的通用批量更新方式

    解讀tk.mybatis的通用批量更新方式

    這篇文章主要介紹了關(guān)于tk.mybatis的通用批量更新方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-08-08

最新評(píng)論