路徑問題:必定要注意此位置是否須要加入"/"java
文件上傳方式:被動模式apache
vsftp完整配置:數組
#
# The default compiled in settings are fairly paranoid. This sample file
# loosens things up a bit, to make the ftp daemon more usable.
# Please see vsftpd.conf.5 for all compiled in defaults.
#
# READ THIS: This example file is NOT an exhaustive list of vsftpd options.
# Please read the vsftpd.conf.5 manual page to get a full idea of vsftpd's
# capabilities.
#
# Allow anonymous FTP? (Beware - allowed by default if you comment this out).
anonymous_enable=NO
#
# Uncomment this to allow local users to log in.
# When SELinux is enforcing check for SE bool ftp_home_dir
local_enable=YES
#
# Uncomment this to enable any form of FTP write command.
write_enable=YES
#
# Default umask for local users is 077. You may wish to change this to 022,
# if your users expect that (022 is used by most other ftpd's)
local_umask=022
#local_umask=002
#
# Uncomment this to allow the anonymous FTP user to upload files. This only
# has an effect if the above global write enable is activated. Also, you will
# obviously need to create a directory writable by the FTP user.
# When SELinux is enforcing check for SE bool allow_ftpd_anon_write, allow_ftpd_full_access
#anon_upload_enable=YES
#
# Uncomment this if you want the anonymous FTP user to be able to create
# new directories.
#容許用戶建立目錄
#anon_mkdir_write_enable=YES
#
# Activate directory messages - messages given to remote users when they
# go into a certain directory.
dirmessage_enable=YES
#
# Activate logging of uploads/downloads.
xferlog_enable=YES
#
# Make sure PORT transfer connections originate from port 20 (ftp-data).
connect_from_port_20=YES
#
# If you want, you can arrange for uploaded anonymous files to be owned by
# a different user. Note! Using "root" for uploaded files is not
# recommended!
#chown_uploads=YES
#chown_username=whoever
#
# You may override where the log file goes if you like. The default is shown
# below.
#xferlog_file=/var/log/xferlog
#
# If you want, you can have your log file in standard ftpd xferlog format.
# Note that the default log file location is /var/log/xferlog in this case.
xferlog_std_format=YES
#
# You may change the default value for timing out an idle session.
#idle_session_timeout=600
#
# You may change the default value for timing out a data connection.
#data_connection_timeout=120
#
# It is recommended that you define on your system a unique user which the
# ftp server can use as a totally isolated and unprivileged user.
#nopriv_user=ftpsecure
#
# Enable this and the server will recognise asynchronous ABOR requests. Not
# recommended for security (the code is non-trivial). Not enabling it,
# however, may confuse older FTP clients.
#async_abor_enable=YES
#
# By default the server will pretend to allow ASCII mode but in fact ignore
# the request. Turn on the below options to have the server actually do ASCII
# mangling on files when in ASCII mode. The vsftpd.conf(5) man page explains
# the behaviour when these options are disabled.
# Beware that on some FTP servers, ASCII support allows a denial of service
# attack (DoS) via the command "SIZE /big/file" in ASCII mode. vsftpd
# predicted this attack and has always been safe, reporting the size of the
# raw file.
# ASCII mangling is a horrible feature of the protocol.
#開啓
#ascii_upload_enable=YES
#開啓
#ascii_download_enable=YES
#
# You may fully customise the login banner string:
#ftpd_banner=Welcome to blah FTP service.
#
# You may specify a file of disallowed anonymous e-mail addresses. Apparently
# useful for combatting certain DoS attacks.
#deny_email_enable=YES
# (default follows)
#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)
#開啓用限定用戶在其主目錄下,開啓後需加入allow_writeable_chroot=YES chroot_local_user=YES
#chroot_list_enable=YES
# (default follows)
#chroot_list_file=/etc/vsftpd/chroot_list
#
# You may activate the "-R" option to the builtin ls. This is disabled by
# default to avoid remote users being able to cause excessive I/O on large
# sites. However, some broken FTP clients such as "ncftp" and "mirror" assume
# the presence of the "-R" option, so there is a strong case for enabling it.
#ls_recurse_enable=YES
#
# When "listen" directive is enabled, vsftpd runs in standalone mode and
# listens on IPv4 sockets. This directive cannot be used in conjunction
# with the listen_ipv6 directive.
#listen=NO
listen=YES
#
# This directive enables listening on IPv6 sockets. By default, listening
# on the IPv6 "any" address (::) will accept connections from both IPv6
# and IPv4 clients. It is not necessary to listen on *both* IPv4 and IPv6
# sockets. If you want that (perhaps because you want to listen on specific
# addresses) then you must run two copies of vsftpd with two configuration
# files.
# Make sure, that one of the listen options is commented !!
#listen_ipv6=YES
listen_ipv6=NO
pam_service_name=vsftpd
userlist_enable=YES
tcp_wrappers=YES
#設置訪問目錄 local_root=/home/ftpuser/ allow_writeable_chroot=YES
#開啓被動模式 pasv_enable=YES #被動模式端口範圍 pasv_min_port=6000 pasv_max_port=6010 #須要加入外部ip,不然被動模式會失敗 pasv_address=39.96.38.179 pasv_addr_resolve=YES
接下來,開放阿里雲服務器端口。服務器
20,21端口開放(22端口已默認開放)session
接下來,使用java代碼進行文件操做。app
FtpUtil.java工具類socket
package com.sun123.ftp.util; import java.io.BufferedOutputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.SocketException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.commons.net.ftp.FTP; import org.apache.commons.net.ftp.FTPClient; import org.apache.commons.net.ftp.FTPReply; /** * ftp工具類 */ public class FtpUtil { private final static Log logger = LogFactory.getLog(FtpUtil.class); /** 本地字符編碼 */ private static String LOCAL_CHARSET = "GBK"; // FTP協議裏面,規定文件名編碼爲iso-8859-1 private static String SERVER_CHARSET = "ISO-8859-1"; /** * 獲取FTPClient對象 * * @param ftpHost * FTP主機服務器 * * @param ftpPassword * FTP 登陸密碼 * * @param ftpUserName * FTP登陸用戶名 * * @param ftpPort * FTP端口 默認爲21 * * @return */ public static FTPClient getFTPClient(String ftpHost, int ftpPort, String ftpUserName, String ftpPassword) { FTPClient ftpClient = null; try { ftpClient = new FTPClient(); ftpClient.connect(ftpHost, ftpPort);// 鏈接FTP服務器 ftpClient.login(ftpUserName, ftpPassword);// 登錄FTP服務器 if (!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) { logger.info("未鏈接到FTP,用戶名或密碼錯誤。"); ftpClient.disconnect(); } else { logger.info("FTP鏈接成功。"); } } catch (SocketException e) { e.printStackTrace(); logger.info("FTP的IP地址可能錯誤,請正確配置。"); } catch (IOException e) { e.printStackTrace(); logger.info("FTP的端口錯誤,請正確配置。"); } return ftpClient; } /** * 從FTP服務器下載文件 * * @param ftpHost FTP IP地址 * * @param ftpUserName FTP 用戶名 * * @param ftpPassword FTP用戶名密碼 * * @param ftpPort FTP端口 * * @param ftpPath FTP服務器中文件所在路徑 格式: ftptest/aa * * @param localPath 下載到本地的位置 格式:H:/download * * @param fileName 文件名稱 */ public static void downloadFtpFile(String ftpHost, String ftpUserName, String ftpPassword, int ftpPort, String ftpPath, String localPath, String fileName) { FTPClient ftpClient = null; try { ftpClient = getFTPClient(ftpHost, ftpPort, ftpUserName, ftpPassword); // 設置上傳文件的類型爲二進制類型 if (FTPReply.isPositiveCompletion(ftpClient.sendCommand("OPTS UTF8", "ON"))) {// 開啓服務器對UTF-8的支持,若是服務器支持就用UTF-8編碼,不然就使用本地編碼(GBK). LOCAL_CHARSET = "UTF-8"; } ftpClient.setControlEncoding(LOCAL_CHARSET); ftpClient.enterLocalPassiveMode();// 設置被動模式 ftpClient.setFileType(FTP.BINARY_FILE_TYPE);// 設置傳輸的模式 // 上傳文件 //對中文文件名進行轉碼,不然中文名稱的文件下載失敗 String fileNameTemp = new String(fileName.getBytes(LOCAL_CHARSET), SERVER_CHARSET); ftpClient.changeWorkingDirectory(ftpPath); InputStream retrieveFileStream = ftpClient.retrieveFileStream(fileNameTemp); // 第一種方式下載文件(推薦) /* File localFile = new File(localPath + File.separatorChar + fileName); OutputStream os = new FileOutputStream(localFile); ftpClient.retrieveFile(fileName, os); os.close();*/ // 第二種方式下載:將輸入流轉成字節,再生成文件,這種方式方便將字節數組直接返回給前臺jsp頁面 byte[] input2byte = input2byte(retrieveFileStream); byte2File(input2byte, localPath, fileName); if(null != retrieveFileStream){ retrieveFileStream.close(); } } catch (FileNotFoundException e) { logger.error("沒有找到" + ftpPath + "文件"); e.printStackTrace(); } catch (SocketException e) { logger.error("鏈接FTP失敗."); e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); logger.error("文件讀取錯誤。"); e.printStackTrace(); } finally { if (ftpClient.isConnected()) { try { //退出登陸 ftpClient.logout(); //關閉鏈接 ftpClient.disconnect(); } catch (IOException e) { } } } } /** * Description: 向FTP服務器上傳文件 * * @param host * FTP服務器hostname * @param port * FTP服務器端口 * @param username * FTP登陸帳號 * @param password * FTP登陸密碼 * @param basePath * FTP服務器基礎目錄 * @param filePath * FTP服務器文件存放路徑。例如分日期存放:/2015/01/01。文件的路徑爲basePath+filePath * @param filename * 上傳到FTP服務器上的文件名 * @param input * 輸入流 * @return 成功返回true,不然返回false */ /*String host, int port, String username, String password, String remotePath, String fileName, String localPath*/ public static boolean uploadFile(String ftpHost, int ftpPort, String ftpUserName, String ftpPassword, String basePath, String filePath, String filename, InputStream input) { boolean result = false; FTPClient ftpClient = null; try { int reply; ftpClient = getFTPClient(ftpHost, ftpPort, ftpUserName, ftpPassword); reply = ftpClient.getReplyCode(); if (!FTPReply.isPositiveCompletion(reply)) { ftpClient.disconnect(); return result; } // 切換到上傳目錄 if (!ftpClient.changeWorkingDirectory(basePath + filePath)) { // 若是目錄不存在建立目錄 String[] dirs = filePath.split("/"); String tempPath = basePath; for (String dir : dirs) { if (null == dir || "".equals(dir)) continue; tempPath += "/" + dir; if (!ftpClient.changeWorkingDirectory(tempPath)) { if (!ftpClient.makeDirectory(tempPath)) { return result; } else { ftpClient.changeWorkingDirectory(tempPath); } } } } // 設置上傳文件的類型爲二進制類型 if (FTPReply.isPositiveCompletion(ftpClient.sendCommand("OPTS UTF8", "ON"))) {// 開啓服務器對UTF-8的支持,若是服務器支持就用UTF-8編碼,不然就使用本地編碼(GBK). LOCAL_CHARSET = "UTF-8"; } ftpClient.setControlEncoding(LOCAL_CHARSET); ftpClient.enterLocalPassiveMode();// 設置被動模式 ftpClient.setFileType(FTP.BINARY_FILE_TYPE);// 設置傳輸的模式 // 上傳文件 filename = new String(filename.getBytes(LOCAL_CHARSET), SERVER_CHARSET); if (!ftpClient.storeFile(filename, input)) { return result; } if(null != input){ input.close(); } result = true; } catch (IOException e) { e.printStackTrace(); } finally { if (ftpClient.isConnected()) { try { //退出登陸 ftpClient.logout(); //關閉鏈接 ftpClient.disconnect(); } catch (IOException ioe) { } } } return result; } /** * 刪除文件 * * @param hostname * FTP服務器地址 * @param port * FTP服務器端口號 * @param username * FTP登陸賬號 * @param password * FTP登陸密碼 * @param pathname * FTP服務器保存目錄 * @param filename * 要刪除的文件名稱 * @return */ public static boolean deleteFile(String ftpHost, int ftpPort, String ftpUserName, String ftpPassword, String pathname, String filename) { boolean flag = false; FTPClient ftpClient = new FTPClient(); try { ftpClient = getFTPClient(ftpHost, ftpPort, ftpUserName, ftpPassword); // 驗證FTP服務器是否登陸成功 int replyCode = ftpClient.getReplyCode(); if (!FTPReply.isPositiveCompletion(replyCode)) { return flag; } // 切換FTP目錄 ftpClient.changeWorkingDirectory(pathname); // 設置上傳文件的類型爲二進制類型 if (FTPReply.isPositiveCompletion(ftpClient.sendCommand("OPTS UTF8", "ON"))) {// 開啓服務器對UTF-8的支持,若是服務器支持就用UTF-8編碼,不然就使用本地編碼(GBK). LOCAL_CHARSET = "UTF-8"; } ftpClient.setControlEncoding(LOCAL_CHARSET); ftpClient.enterLocalPassiveMode();// 設置被動模式 ftpClient.setFileType(FTP.BINARY_FILE_TYPE);// 設置傳輸的模式 //對中文名稱進行轉碼 filename = new String(filename.getBytes(LOCAL_CHARSET), SERVER_CHARSET); ftpClient.dele(filename); flag = true; } catch (Exception e) { e.printStackTrace(); } finally { if (ftpClient.isConnected()) { try { //退出登陸 ftpClient.logout(); //關閉鏈接 ftpClient.disconnect(); } catch (IOException e) { } } } return flag; } // 將字節數組轉換爲輸入流 public static final InputStream byte2Input(byte[] buf) { return new ByteArrayInputStream(buf); } // 將輸入流轉爲byte[] public static final byte[] input2byte(InputStream inStream) throws IOException { ByteArrayOutputStream swapStream = new ByteArrayOutputStream(); byte[] buff = new byte[100]; int rc = 0; while ((rc = inStream.read(buff, 0, 100)) > 0) { swapStream.write(buff, 0, rc); } byte[] in2b = swapStream.toByteArray(); return in2b; } // 將byte[]轉爲文件 public static void byte2File(byte[] buf, String filePath, String fileName) { BufferedOutputStream bos = null; FileOutputStream fos = null; File file = null; try { File dir = new File(filePath); if (!dir.exists() && dir.isDirectory()) { dir.mkdirs(); } file = new File(filePath + File.separator + fileName); fos = new FileOutputStream(file); bos = new BufferedOutputStream(fos); bos.write(buf); } catch (Exception e) { e.printStackTrace(); } finally { if (bos != null) { try { bos.close(); } catch (IOException e) { e.printStackTrace(); } } if (fos != null) { try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
FtpTest.java測試類:jsp
package com.sun123.ftp.test; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import org.joda.time.DateTime; import com.sun123.ftp.util.FtpUtil; public class FtpTest { public static void main(String[] args) throws FileNotFoundException { //ftp服務器IP地址 String ftpHost = "12.34.56.789"; //僅供參考 //ftp服務器端口 int ftpPort = 21; //ftp服務器用戶名 String ftpUserName = "ftp"; //ftp服務器密碼 String ftpPassword = "123456"; //ftp服務器路徑 //必須有"/" String ftpPath = "/tasksystem/images/stu/headportrait"; //本地路徑 String localPath = "O://"; //文件名 String fileName = "1.jpg"; //下載 //將ftp根目錄下的文件下載至E盤 // FtpUtil.downloadFtpFile(ftpHost, ftpUserName, ftpPassword, ftpPort, ftpPath, localPath, fileName); String imagePath = new DateTime().toString("/yyyy/MM/dd");//上傳 //將E盤的文件上傳至ftp根目錄 FileInputStream in=new FileInputStream(new File(localPath + fileName)); FtpUtil.uploadFile(ftpHost, ftpPort, ftpUserName, ftpPassword, ftpPath , imagePath, fileName, in); //刪除 //刪除ftp根目錄下的文件 //FtpUtil.deleteFile(ftpHost, ftpPort, ftpUserName, ftpPassword, ftpPath + imagePath, "1111556507044860411.jpg"); } }
經測試,文件上傳和刪除均有效。async
說明:joda-time時間插件很好用tcp
點擊進行源碼下載
參考:https://blog.csdn.net/ljj2312/article/details/78968037