CentOS6.5下搭建FTP服务器 + Java上传文件

来源:互联网 发布:算法书籍经典 编辑:程序博客网 时间:2024/05/16 11:49

项目中开始使用http协议进行传输文件,但是终端提出传输的字节超过限度,要使用FTP文件服务器进行断点续传,每次1k的进行传输. 老大让我在开发环境中搭建vsftp服务器,一起没操作过,现在记录下来留做以后的回顾学习;

vsftp简介

vsftpd是一款在Linux发行版中最受推崇的FTP服务器程序。特点是小巧轻快,安全易用。ftp作为文件服务器,断点续传是和http传输的一个区别;

CentOS6.5安装vsftp

以管理员(root)身份进行一下操作:

1.检测是否安装了vsftp

[root@dev04 ~]# rpm -qa |grep vsftpdvsftpd-2.2.2-14.el6.x86_64
我是安装过的, 命令下方返回的是我的vsftp版本

检测到安装过后如果想卸载执行:

rpm -e vsftpd
再执行
rpm -qa |grep vsftpd
查看卸载是否成功,如果成功会返回卸载的vsftp的版本

2.安装vsftp

yum install vsftpd* -y

3.设置开机自启vsftp ftp服务

chkconfig vsftpd on

4.启动ftp服务

[root@dev04 vsftpd]# service vsftpd start
关闭服务:
[root@dev04 vsftpd]# service vsftpd stop
重启服务:
[root@dev04 vsftpd]# service vsftpd restart

5.配置vsftp的配置文件vsftpd.conf

在 /etc/vsftpd目录下有三个文件和一个执行命令?
-rw------- 1 root root  125 Jul 24  2015 ftpusers-rw------- 1 root root  371 Apr  6 14:11 user_list-rw------- 1 root root 4737 Apr  1 15:51 vsftpd.conf-rwxr--r-- 1 root root  338 Jul 24  2015 vsftpd_conf_migrate.sh
要修改的配置信息都在vsftpd.conf配置文件中,修改配置文件之前最好进行备份
[root@dev04 vsftpd]# cp vsftpd.conf vsftpd.conf.bak

再进行编辑修改配置文件
[root@dev04 vsftpd]# vim /etc/vsftpd/vsftpd.conf

主要的就是匿名用户的访问权限和 新增本地用户设置访问权限

因为要提供给终端使用FTP服务器映射的公网进行访问,又不行暴露服务器文件所在的目录,
必须支持匿名用户的访问, ftp匿名用户默认目录为 /var/ftp/pub目录下
vsftpd.conf配置文件主要修改
anonymous_enable=YES   // 支持匿名登录,如果改为NO不支持匿名登录
write_enable=YES//支持读
anon_upload_enable=YES//支持匿名改写
anon_mkdir_write_enable=YES//支持匿名用户创建子目录

6.创建用户ftpuser,指定目录/home/ftpuser,禁止SSH登录权限

useradd -d /home/ftpuser -g ftp -s /sbin/nologin ftpuser
给帐号设置密码
passwd ftpuer
注意: 在设置密码时会提示什么密码过于简单,或者密码为单词词组等等,不用管,它已经进行设置了,要确认两次输入的密码都相同;输入两次密码后出现successful.....就代表设置密码成功了;

创建用户时遇到的问题:

1.我开始是关闭匿名用户的登录权限的,设置了ftpuser, 终端访问时必须要输入 ftp://username:password@IP地址:port/访问路径   这样会暴露文件存放的路径,不合理(我觉得可能是我设置ftpuser用户时没有在配置文件中配置默认目录什么的,因为按照前面这样访问时候默认进入默认目录/ftpuser的,这点没怎么清楚==)
2.项目中上传文件原本是使用fastDFS文件服务器的,现在改为FTP,将固件上传到匿名用户目录下,提供终端下载
新建了anon用户将默认目录设置为匿名访问的目录 /var/ftp/pub

useradd -d /var/ftp -g ftp -s /sbin/nologin anon
在使用java进行上传文件时发现anon用户不能连接上该目录,查资料说是没有对目录进行设置权限
LINUX下搭建FTP服务器--非宁静无以致远

注意的事项是的:

1、pub目录的权限不能全开,全开会报错,chmod 755 -R pub

2、但是这样也会带来一个问题,当匿名用户登录后,在pub下的newftp目录下想上传一个文件,会报错,因为匿名用户(ftp)无法在该目录下(该目录属于root用户)创建一个新文件的,因为该目录下他没有权限,所以要加入其他用户(o)的写权限,chmod o+w /var/ftp/pub/.

现在权限变为:
drwxr-xrwx 2 root root   4096 06-20 16:55 pub
其实就是757的权限,此时匿名用户(ftp)就可以在该目录下上传文件了。


最后重启服务: service vsftpd restart


附上MultipartFile使用ftp上传文件

1.maven项目中添加pom文件

<!-- https://mvnrepository.com/artifact/commons-net/commons-net --><dependency><groupId>commons-net</groupId><artifactId>commons-net</artifactId><version>3.6</version></dependency>

2.ftp配置文件 ftp_client.properties

#公网IP映射地址: 218.205.115.XXX 2121

ftp_public_network_add = 218.205.115.XXX#FTP公网端口ftp_public_network_port = 2121#FTP服务器地址172.23.28.XXXftp_host = 172.23.28.XXX#21ftp_port = 21##匿名用户 anonymous 创建一个用户名为ftpuser,目录在pub下,具有增删改查/新建子目录权限ftp_user_name = ftpuserftp_user_pwd = ftpuser#匿名登录上传目录 /var/ftp/pubremoteFile_addr = /var/ftp/pub/

3.自定义配置文件的pojo类,提高代码扩展性

@Componentpublic class FTPConfig {    /** FTP服务器IP地址 */    @Value("#{configProperties['ftp_host']}")    private String fTPhost = "localhost";    /** FTP服务器端口 */    @Value("#{configProperties['ftp_port']}")    private int ftpPort = 21;    /** FTP服务器用户名 */    @Value("#{configProperties['ftp_user_name']}")    private String ftpUserName;    /** FTP用户密码 */    @Value("#{configProperties['ftp_user_pwd']}")    private String ftpUserPasswd;    /** 用户远程上传文件存储目录 */    @Value("#{configProperties['remoteFile_addr']}")    private String remoteFileAddr;    /** FTP公网映射地址 */    @Value("#{configProperties['ftp_public_network_add']}")    private String ftpNetAdd;    /** FTP公网端口 */    @Value("#{configProperties['ftp_public_network_port']}")    private int ftpNetPort = 2121;
}

4.FTP上传下载的工具类FTPFileManager

/** * @Type ftpClientFileManager.java * @Desc  * @author 123 * @date 2017年3月31日 下午2:50:58 * @version  */@Servicepublic class FTPFileManager {    private static final Logger logger = LoggerFactory.getLogger(FTPFileManager.class);    private FTPClient ftpClient = new FTPClient();    /** 路径分隔符 */    private static final String SEPARATOR = "/";    /** FTP访问路径前缀 */    private static final String FTP_PREFIX = "ftp://";    @Autowired    private FTPConfig config;    /**     * @Title: upload      *     * @Description: 文件上传     *     * @param uploadFile     *          MultipartFile     * @return     *          返回保存路径 + 文件名     * @throws Exception      *     */    public String upload(MultipartFile uploadFile) throws Exception {        ftpClient = new FTPClient();        ftpClient.connect(config.getfTPhost(), config.getFtpPort());        ftpClient.login(config.getFtpUserName(), config.getFtpUserPasswd());        //设置ftp字节流        ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);        int reply;        reply = ftpClient.getReplyCode();        if (!FTPReply.isPositiveCompletion(reply)) {            ftpClient.disconnect();            return null;        }        ftpClient.enterLocalPassiveMode();        String basePath = config.getRemoteFileAddr();        ftpClient.changeWorkingDirectory(basePath);        //为当天日期文件创建追加目录        Date today = new Date();        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");        String appendFile = sdf.format(today);        //切换到上传目录        if (!ftpClient.changeWorkingDirectory(basePath + appendFile)) {            //如果目录不存在创建目录            String[] dirs = appendFile.split(SEPARATOR);            String tempTargetPath = basePath;            for (String dir : dirs) {                if (null == dir || "".equals(dir))                    continue;                tempTargetPath += SEPARATOR + dir;                if (!ftpClient.changeWorkingDirectory(tempTargetPath)) {                    if (!ftpClient.makeDirectory(tempTargetPath)) {                        logger.error("ftp文件目录创建失败!");                        return null;                    } else {                        ftpClient.changeWorkingDirectory(tempTargetPath);                    }                }            }        }        String fileName = new String(uploadFile.getOriginalFilename().getBytes("utf-8"),                "iso-8859-1");        /**         * 避免文件过多后出现重名,设置30位随机数为文件名称         */        // 获取文件扩展名 形如: .txt        String fileExt = fileName.substring(fileName.lastIndexOf("."));        String newFileName = RandomUtils.randomAlphanumericStrictly(30) + fileExt;        InputStream is = uploadFile.getInputStream();        if (!ftpClient.storeFile(newFileName, is)) {            logger.error("文件{}存储过程出错", fileName);            return null;        }        is.close();        ftpClient.disconnect();        /* String finalFile = basePath + SEPARATOR + appendFile + SEPARATOR + fileName;*/        //直接存储为匿名用户可直接访问下载的地址        String finalFile = FTP_PREFIX + config.getFtpNetAdd() + ":" + config.getFtpNetPort()                + SEPARATOR + "pub" + SEPARATOR + appendFile + SEPARATOR + newFileName;        logger.info("文件上传FTP服务器成功, 访问文件路径为 : " + finalFile);        return finalFile;    }    /**      * 从FTP服务器上下载文件      * @param remote 远程文件路径      * @param local 本地文件路径      * @return 是否成功      * @throws Exception      */    public boolean download(String remote, String local) throws Exception {        ftpClient = new FTPClient();        ftpClient.connect(config.getfTPhost(), config.getFtpPort());        ftpClient.login(config.getFtpUserName(), config.getFtpUserPasswd());        ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);        int reply;        reply = ftpClient.getReplyCode();        if (!FTPReply.isPositiveCompletion(reply)) {            ftpClient.disconnect();            return false;        }        ftpClient.enterLocalPassiveMode();        ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);        boolean result;        File f = new File(local);        FTPFile[] files = ftpClient.listFiles(remote);        if (files.length != 1) {            System.out.println("远程文件不唯一");            ftpClient.disconnect();            return false;        }        long lRemoteSize = files[0].getSize();        if (f.exists()) {            OutputStream out = new FileOutputStream(f, true);            System.out.println("本地文件大小为:" + f.length());            if (f.length() >= lRemoteSize) {                logger.error("本地文件大小大于远程文件大小,下载中止");                out.close();                ftpClient.disconnect();                return false;            }            ftpClient.setRestartOffset(f.length());            result = ftpClient.retrieveFile(remote, out);            out.close();        } else {            OutputStream out = new FileOutputStream(f);            result = ftpClient.retrieveFile(remote, out);            out.close();        }        ftpClient.disconnect();        return result;    }}/** * Revision history * ------------------------------------------------------------------------- *  * Date Author Note * ------------------------------------------------------------------------- * 2017年3月31日 123 creat */


此时,用户可以通过公网映射的IP进行访问, 类似 ftp://218.205.115.XXXX:2121/pub/2017/04/06/4cn91c2dRffmQ8diQ4mvDRo5m2lWtr.txt
由于项目中没使用到文件下载,我只在本地进行了简单的下载centOS中FTP文件测试.



简单的记录.

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
支持断点续传的上传方法
/**      * 上传文件到FTP服务器,支持断点续传      * @param local 本地文件名称,绝对路径      * @param remote 远程文件路径,使用/home/directory1/subdirectory/file.ext 按照Linux上的路径指定方式,支持多级目录嵌套,支持递归创建不存在的目录结构      * @return 上传结果      * @throws IOException      */    public String upload(String local, String remote) throws IOException {        //设置PassiveMode传输          ftpClient.enterLocalPassiveMode();        //设置以二进制流的方式传输          ftpClient.setFileType(FTP.BINARY_FILE_TYPE);        String uploadStatus;        //对远程目录的处理          String remoteFileName = remote;        if (remote.contains("/")) {            remoteFileName = remote.substring(remote.lastIndexOf("/") + 1);            String directory = remote.substring(0, remote.lastIndexOf("/") + 1);            if (!directory.equalsIgnoreCase("/") && !ftpClient.changeWorkingDirectory(directory)) {                //如果远程目录不存在,则递归创建远程服务器目录                  int start = 0;                int end = 0;                if (directory.startsWith("/")) {                    start = 1;                } else {                    start = 0;                }                end = directory.indexOf("/", start);                while (true) {                    String subDirectory = remote.substring(start, end);                    if (!ftpClient.changeWorkingDirectory(subDirectory)) {                        if (ftpClient.makeDirectory(subDirectory)) {                            ftpClient.changeWorkingDirectory(subDirectory);                        } else {                            System.out.println("创建目录失败");                            return UploadStatus.Create_Directory_Fail;                        }                    }                    start = end + 1;                    end = directory.indexOf("/", start);                    //检查所有目录是否创建完毕                      if (end <= start) {                        break;                    }                }            }        }        //检查远程是否存在文件          FTPFile[] files = ftpClient.listFiles(remoteFileName);        if (files.length == 1) {            long remoteSize = files[0].getSize();            File f = new File(local);            long localSize = f.length();            if (remoteSize == localSize) {                return UploadStatus.File_Exits;            } else if (remoteSize > localSize) {                return UploadStatus.Remote_Bigger_Local;            }            //尝试移动文件内读取指针,实现断点续传              InputStream is = new FileInputStream(f);            if (is.skip(remoteSize) == remoteSize) {                //设置文件开始                ftpClient.setRestartOffset(remoteSize);                if (ftpClient.storeFile(remote, is)) {                    is.close();                    return UploadStatus.Upload_From_Break_Success;                }            }            //如果断点续传没有成功,则删除服务器上文件,重新上传              if (!ftpClient.deleteFile(remoteFileName)) {                return UploadStatus.Delete_Remote_Faild;            }            is = new FileInputStream(f);            if (ftpClient.storeFile(remote, is)) {                uploadStatus = UploadStatus.Upload_New_File_Success;            } else {                uploadStatus = UploadStatus.Upload_New_File_Failed;            }            is.close();        } else {            InputStream is = new FileInputStream(local);            if (ftpClient.storeFile(remoteFileName, is)) {                uploadStatus = UploadStatus.Upload_New_File_Success;            } else {                uploadStatus = UploadStatus.Upload_New_File_Failed;            }            is.close();        }        return uploadStatus;    }












0 0
原创粉丝点击