zoukankan      html  css  js  c++  java
  • 阿里云服务器+ftp文件操作+基于Centos7的vsftpd配置

    路径问题:一定要注意此位置是否需要加入"/"

    文件上传方式:被动模式

    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端口已默认开放)

    接下来,使用java代码进行文件操作。

    FtpUtil.java工具类

    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测试类:

    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");
            
            
        }
    }  

    经测试,文件上传和删除均有效。

    说明:joda-time时间插件很好用

    点击进行源码下载

    参考:https://blog.csdn.net/ljj2312/article/details/78968037

  • 相关阅读:
    WinForm 窗体应用程序(初步)之一
    ADO.NET
    面向对象思想
    数据库原理
    HTML学习总结
    c# 学习心得(2)
    c# 学习心得(1)
    《大话数据结构》读书笔记(2)
    《大话数据结构》读书笔记(1)
    ASP.NET Core学习总结(3)
  • 原文地址:https://www.cnblogs.com/116970u/p/10789513.html
Copyright © 2011-2022 走看看