FTP服务安装 与java文件上传与下载

1.yum安装FTP服务

      yum install vsftpd

2.修改配置

     vi /etc/vsftpd/vsftpd.conf

        设置监听端口 listen_port=7019

     vim /etc/pam.d/vsftpd

        注释这一行#auth       required    pam_shells.so

3.启动服务

     cetoos 7 操作为 /bin/systemctl restart vsftpd.service

     centoos 6 操作为 service vsftpd restart

4.设置开机启动

      chkconfig --level 35 vsftpd on

5.添加用户

      useradd ftpadmin -s /sbin/nologin

6.设置密码

     passwd ftpadmin     (之后输入两次密码)

 

 

安装方式2

搭建FTP服务器:
关闭linux防火墙
查看状态:systemctl status firewalld.service
永久关闭:systemctl disable firewalld.service
暂停:systemctl stop firewalld.service
关闭selinux
查看状态:getenforce(最终显示为disabled)
配置:vim /etc/selinux/config
修改为:SELINUX=disabled
暂停:setenforce 0
重启服务器:reboot
创建用户组:
groupadd  ftpGroup
创建用户:
useradd -d /data/ftp -s /sbin/nologin -g ftpGroup -G root ftpUser
设置用户密码:
passwd ftpUser
用户FTP文件夹赋权限:
chown ftpUser /data/ftp
cd /data
chmod 777 ftp
安装FTP:
yum install -y vsftpd
设置开机启动:
chkconfig vsftpd on
查看FTP接口:
netstat -antup|grep ftp
进入vsftpd主配置文件:
vim /etc/vsftpd/vsftpd.conf
修改为anonymous_enable = NO,这样可以禁止匿名登陆用户登录
重启FTP服务:
service vsftpd restart
530 500 等错误处理:
vim /etc/pam.d/vsftpd
注释掉:auth required pam_shells.so
(或将auth required pam_shells.so修改为->auth required pam_nologin.so即可)
系统内部尝试自己访问:
ftp ip
外网访问-浏览器访问:
ftp://ip 
FTP工具访问:

 

 

 

java 代码上传连接

 

pom文件

<dependency>
    <groupId>commons-net</groupId>
    <artifactId>commons-net</artifactId>
    <version>3.6</version>
</dependency>

 



import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;

import java.io.*;

public class MyFtpUtil {

    final private static int sum = 100;//最大进度条
    final private static String logo = "=";//进度标识

    /**
     * 获取FTP服务器客户端
     *
     * @param hostname 主机名
     * @param port     端口
     * @param username 用户名
     * @param password 密码
     * @param type     请求模式,主动与被动 z/b
     * @return ftp客户端
     * @throws Exception
     */
    public static FTPClient getClient(String hostname, int port, String username, String password, String type) throws Exception {
        FTPClient ftpClient = new FTPClient();
        ftpClient.connect(hostname, port);
        ftpClient.setControlEncoding("GBK");
        //连接与登录异常排查
        if (!FTPReply.isPositiveCompletion(ftpClient.getReplyCode()) || !ftpClient.login(username, password)) {
            throw new Exception();
        }
        if (type.equals("z")) {//设置主动传输或者被动传输
            ftpClient.enterLocalActiveMode();
        } else if (type.equals("b")) {
            ftpClient.enterLocalPassiveMode();
        }
        ftpClient.setFileType(FTP.BINARY_FILE_TYPE);//设置以二进制方式传输
        return ftpClient;
    }

    /**
     * 释放资源
     *
     * @throws IOException
     */

    public static void close(Object... objects) throws IOException {
        for (Object object : objects) {
            if (object instanceof FTPClient) {
                FTPClient ftpClient = (FTPClient) object;
                if (ftpClient != null && ftpClient.isConnected()) {
                    ftpClient.disconnect();
                }
            } else if (object instanceof InputStream) {
                InputStream inputStream = (InputStream) object;
                if (inputStream != null) {
                    inputStream.close();
                }
            } else if (object instanceof OutputStream) {
                OutputStream outputStream = (OutputStream) object;
                if (outputStream != null) {
                    outputStream.close();
                }
            } else if (object instanceof RandomAccessFile) {
                RandomAccessFile randomAccessFile = (RandomAccessFile) object;
                if (randomAccessFile != null) {
                    randomAccessFile.close();
                }
            }
        }
    }

    /**
     * 显示最长进度与历史进度
     *
     * @param process 历史进度条
     */
    private static void historySchedule(Long process) {
        System.out.print("总量: ");
        for (int i = 0; i < sum; i++) {
            System.out.print(logo);
        }
        System.out.println();
        System.out.print("当前: ");
        for (int i = 0; i < process; i++) {
            System.out.print(logo);
        }
    }

    /**
     * 进度增加
     *
     * @param status 是否结束进度换行
     */
    private static void addschedule(boolean status, long frequency) {
        if (status) {
            System.out.println();
        } else {
            for (int i = 0; i < frequency; i++) {
                System.out.print(logo);
            }
        }
    }

    /**
     * @param byteLength 传输大小,b
     * @param startTime  起始时间,毫秒
     * @param endTime    结束时间,毫秒
     */
    private static void calculationSpeed(long byteLength, long startTime, long endTime) {
        double scends = (endTime - startTime) / 1000.0;//处理时间秒
        double v = byteLength / scends;
        String unit[] = new String[]{"b", "k", "M", "G", "T", "P"};
        int i = 0;
        while (v > 1 << 10) {//v < 1024
            i++;
            v = v / 1024.0;
        }
        System.out.println(String.format("速度: %.2f %s/s", v, unit[i]));
        System.out.println(String.format("传输时间: %.2f 秒", scends));
        System.out.println(String.format("传输大小: %s b", byteLength));
    }

    /**
     * 递归创建远程服务器目录
     *
     * @param serverDirPath 远程服务器文件绝对路径
     * @param ftpClient     FTPClient对象
     * @return 目录创建是否成功
     * @throws IOException
     */
    public static void createDirecroty(String serverDirPath, FTPClient ftpClient) throws IOException {
        String directory = serverDirPath.substring(0, serverDirPath.lastIndexOf("/") + 1);
        if (!directory.equalsIgnoreCase("/") && !ftpClient.changeWorkingDirectory(new String(directory.getBytes("GBK"), "iso-8859-1"))) {
            //如果远程目录不存在,则递归创建远程服务器目录
            int end, start = 0;
            if (directory.startsWith("/")) {
                start = 1;
            }
            end = directory.indexOf("/", start);
            while (true) {
                String subDirectory = new String(serverDirPath.substring(start, end).getBytes("GBK"), "iso-8859-1");
                if (!ftpClient.changeWorkingDirectory(subDirectory)) {
                    if (ftpClient.makeDirectory(subDirectory)) {
                        ftpClient.changeWorkingDirectory(subDirectory);
                    } else {
                        throw new IOException("创建远程目录失败");
                    }
                }
                start = end + 1;
                end = directory.indexOf("/", start);
                //检查所有目录是否创建完毕
                if (end <= start) {
                    break;
                }
            }
        }
    }

    /**
     * 上传文件控制端
     *
     * @param ftpClient      ftp客户端对象
     * @param localFilePath  本地文件名称,绝对路径
     * @param serverFilePath 远程文件路径,支持递归创建不存在的目录结构
     * @param buffer         上传文件buffer缓存大小
     * @return 上传结果
     * @throws IOException
     */
    public static String uploadController(FTPClient ftpClient, String localFilePath, String serverFilePath, int buffer) throws IOException {
        //设置以二进制流的方式传输
        ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
        ftpClient.setControlEncoding("GBK");
        //对远程目录的处理
        String serverFileName = serverFilePath;
        if (serverFilePath.contains("/")) {
            serverFileName = serverFilePath.substring(serverFilePath.lastIndexOf("/") + 1);
            //创建服务器远程目录结构,创建失败直接抛出异常返回
            createDirecroty(serverFilePath, ftpClient);
        }
        //检查远程是否存在文件
        long serverFileSize = 0;
        File f = new File(localFilePath);
        if (!f.exists()) {
            throw new IOException("本地文件不存在");
        }
        FTPFile[] files = ftpClient.listFiles(new String(serverFileName.getBytes("GBK"), "iso-8859-1"));
        if (files.length == 1) {
            serverFileSize = files[0].getSize();
            long localFileSize = f.length();
            if (serverFileSize == localFileSize) {
                throw new IOException("文件已经存在");
            } else if (serverFileSize > localFileSize) {
                throw new IOException("远程文件大于本地文件");
            }
        }
        //serverFileSize表示移动文件内读取指针,实现断点续传
        try {
            uploadFile(ftpClient, serverFileName, f, serverFileSize, buffer);
        } catch (IOException e) {
            if (!ftpClient.deleteFile(serverFileName)) {//如果断点续传没有成功,则删除服务器上文件,重新上传
                throw new IOException("上传失败,重传删除文件失败");
            }
            uploadFile(ftpClient, serverFileName, f, serverFileSize, buffer);
        }
        return "success";
    }

    /**
     * 上传文件到服务器,新上传和断点续传
     *
     * @param ftpClient      FTPClient引用
     * @param serverFile     远程文件名,在上传之前已经将服务器工作目录做了改变
     * @param localFile      本地文件File句柄,绝对路径
     * @param serverFileSize 文件偏移量
     * @param buffer         上传文件buffer大小
     * @return
     * @throws IOException
     */
    public static void uploadFile(FTPClient ftpClient, String serverFile, File localFile, long serverFileSize, int buffer) throws IOException {
        long startTime = System.currentTimeMillis();//起始时间
        Long fileLength = localFile.length();//本地文件大小
        long process;//历史进度
        if (fileLength != 0) {
            process = ((serverFileSize * sum) / fileLength);
        } else {
            process = sum;
        }
        long remaining = fileLength - serverFileSize;//计算文件传输大小
        historySchedule(process);//显示完成进度与历史进度
        RandomAccessFile raf = new RandomAccessFile(localFile, "r");
        OutputStream out = ftpClient.appendFileStream(new String(serverFile.getBytes("GBK"), "iso-8859-1"));
        //断点续传
        if (serverFileSize > 0) {
            ftpClient.setRestartOffset(serverFileSize);//设置远程文件偏移量
            raf.seek(serverFileSize);//偏移读取本地文件
        }
        byte[] bytes = new byte[buffer];
        int c;
        while ((c = raf.read(bytes)) != -1) {
            out.write(bytes, 0, c);
            serverFileSize += c;
            long temp = (serverFileSize * sum) / fileLength;//当前进度
            long addschedule = temp - process;//需要增加的进度条数
            process = temp;//当前进度内存更新
            if (addschedule > 0) {
                addschedule(false, addschedule);//打印进度
            }
        }
        addschedule(true, 0);//换行
        close(out, raf);//关闭资源
        boolean result = ftpClient.completePendingCommand();
        if (!result) {
            throw new IOException("上传失败");
        }
        //计算还需要传输的文件大小
        long endTime = System.currentTimeMillis();//结束时间
        calculationSpeed(remaining, startTime, endTime);
    }

    /**
     * 从FTP服务器上下载文件,支持断点续传,上传百分比汇报
     *
     * @param ftpClient      ftp客户端
     * @param serverFilePath 远程文件路径
     * @param localFilePath  本地文件路径
     * @param buffer         下载文件缓存大小
     * @return 上传的状态
     * @throws IOException
     */
    public static String download(FTPClient ftpClient, String serverFilePath, String localFilePath, int buffer) throws Exception {
        long startTime = System.currentTimeMillis();//起始时间
        //检查远程文件是否存在
        FTPFile[] files = ftpClient.listFiles(new String(serverFilePath.getBytes("GBK"), "iso-8859-1"));
        if (files.length == 0) {
            throw new IOException("下载的文件不存在");
        }
        long serverFileSize = files[0].getSize();//远程文件大小
        long localFileSize = 0;//本地文件大小
        File f = new File(localFilePath);
        long localTemp = 0L;
        //本地存在文件,进行断点下载
        if (f.exists()) {
            localFileSize = f.length();
            //判断本地文件大小是否大于远程文件大小
            if (localFileSize > serverFileSize) {//本地文件与服务器文件大小不同
                throw new IOException("本地文件已经大于服务器文件");
            } else if (localFileSize == serverFileSize) {//本地文件已经存在
                throw new IOException("本地文件已经存在");
            }
        }
        long remaining = serverFileSize - localTemp;//计算文件传输大小
        long process;
        if (serverFileSize != 0) {
            process = ((localFileSize * sum) / serverFileSize);//历史进度
        } else {
            process = sum;
        }
        historySchedule(process);//显示完成进度与历史进度
        FileOutputStream out = new FileOutputStream(f, true);//追加内容
        ftpClient.setRestartOffset(localFileSize);
        InputStream in = ftpClient.retrieveFileStream(new String(serverFilePath.getBytes("GBK"), "iso-8859-1"));
        byte[] bytes = new byte[buffer];
        int c;
        while ((c = in.read(bytes)) != -1) {
            out.write(bytes, 0, c);
            localFileSize += c;
            long temp = (localFileSize * sum) / serverFileSize;//当前进度
            long addschedule = temp - process;//需要增加的进度条数
            process = temp;//当前进度内存更新
            if (addschedule > 0) {
                addschedule(false, addschedule);//打印进度
            }
        }
        addschedule(true, 0);//换行
        close(in, out);
        boolean isDo = ftpClient.completePendingCommand();
        if (!isDo) {
            throw new IOException("下载文件失败");
        }
        long endTime = System.currentTimeMillis();//结束时间
        calculationSpeed(remaining, startTime, endTime);
        return "ok";
    }

    public static void main(String[] args) throws Exception {
        String localPath = "D:\\2.txt";//226,668,403
        String serverPath = "./3.txt";
        FTPClient client = getClient("39.100.228.221", 21, "admin", "123456", "z");
        download(client, serverPath, localPath, 20000);
    }
}

 

FTP操作分为两种 (主动模式与被动模式)

 

主动模式: 

      客户端访问服务端,二者交互是通过客户端的端口交互,客户端不能有防火墙

 

被动模式:

     

     客户端与服务端交互,二者交互是通过服务端的固定端口交互,服务端不能有防火墙

 

被动模式如果服务端有防火墙,那么服务端需要开放一些端口用于与客户端交互

#被动模式是否开启
pasv_enable=YES
#被动模式交互,服务端使用端口范围
pasv_min_port=9910
pasv_max_port=9900

 

 

主动模式需要关闭客户端的防火墙

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小钻风巡山

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值