FTP上传下载工具类

6 篇文章 0 订阅

前言:该工具类使用的是apache的org.apache.commons.net.ftp.FTPClient。

需要导入commons-net依赖:

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

1、FTPUtil:

注:此工具类在windows和linux下面都能使用!

public class FTPUtil {

    /** 本地字符编码 */
    private static String LOCAL_CHARSET = "GBK";
    // FTP协议里面,规定文件名编码为iso-8859-1
    private static String SERVER_CHARSET = "ISO8859-1";

    /**
     * 文件上传
     * @param ip ftp服务器的ip地址
     * @param port ftp服务器的端口
     * @param username 用户名
     * @param password 密码
     * @param uploadPath 目标路径
     * @param file 被上传的文件
     * @return 上传成功返回true
     */
    public static boolean upload(String ip, int port, String username, String password, String uploadPath, File file) {
        boolean result = false;
        FTPClient ftpClient = getFTPClient(ip, port, username, password);
        if (ftpClient == null) {
            file.delete();
            return result;
        }
        try {
            if (uploadPath.startsWith("/")) {
                uploadPath = uploadPath.substring(1);
            }
            String[] paths = uploadPath.split("/");
            for (String path: paths) {
                if (!ftpClient.changeWorkingDirectory(path)) {
                    ftpClient.makeDirectory(path);
                }
                ftpClient.changeWorkingDirectory(path);
            }
            String fileName = file.getName();
            fileName = new String(fileName.getBytes(LOCAL_CHARSET), SERVER_CHARSET);
            BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));
            result = ftpClient.storeFile(fileName, in);
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            close(ftpClient);
        }
        return result;
    }

    /**
     * 单文件下载
     * @param ip ftp服务器的ip地址
     * @param port ftp服务器的端口
     * @param username 用户名
     * @param password 密码
     * @param response 响应对象
     * @param fileName 被下载的文件名
     * @param downloadPath 被下载文件在ftp上的路径
     * @return 下载成功返回true
     */
    public static boolean download(String ip, int port, String username, String password, HttpServletResponse response, String fileName, String downloadPath) {
        boolean result = false;
        FTPClient ftpClient = getFTPClient(ip, port, username, password);
        if (ftpClient == null) {
            return result;
        }
        try {
            response.reset();
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment;filename=" + new String(fileName.getBytes(LOCAL_CHARSET), SERVER_CHARSET));
            ftpClient.changeWorkingDirectory(downloadPath);
            FTPFile[] files = ftpClient.listFiles();
            for (FTPFile file: files) {
                if (file.getName().equals(fileName)) {
                    BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
                    result = ftpClient.retrieveFile(new String(file.getName().getBytes(LOCAL_CHARSET), SERVER_CHARSET), out);
                    out.close();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            close(ftpClient);
        }
        return result;
    }

    /**
     * 删除文件
     * @param ip ftp服务器的ip地址
     * @param port ftp服务器的端口
     * @param username 用户名
     * @param password 密码
     * @param fileName 被删除的文件名
     * @param serverPath 被删除文件在ftp上的路径
     * @return 删除成功返回true
     */
    public static boolean remove(String ip, int port, String username, String password, String fileName, String serverPath) {
        boolean result = false;
        FTPClient ftpClient = getFTPClient(ip, port, username, password);
        if (ftpClient == null) {
            return result;
        }
        try {
            if (!serverPath.endsWith("/")) {
                serverPath += "/";
            }
            ftpClient.changeWorkingDirectory(serverPath);
            FTPFile[] files = ftpClient.listFiles();
            for (FTPFile file: files) {
                if (file.getName().equals(fileName)) {
                    result = ftpClient.deleteFile(serverPath + new String(file.getName().getBytes(LOCAL_CHARSET), SERVER_CHARSET));
                    break;
                }
            }
            boolean flag = removeDirectory(ftpClient, serverPath);
            if (!(result && flag)) {
                result = false;
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            close(ftpClient);
        }
        return result;
    }

    /**
     * 多文件打包zip下载
     * @param ip ftp服务器的ip地址
     * @param port ftp服务器的端口
     * @param username 用户名
     * @param password 密码
     * @param response 响应对象
     * @param fileEntryList 被下载的文件名和路径对应的列表
     * @param zipFileName 压缩文件名称
     * @return 下载成功返回true
     */
    public static boolean zipDownload(String ip, int port, String username, String password, HttpServletResponse response, List<FileEntry> fileEntryList, String zipFileName) {
        boolean result = false;
        FTPClient ftpClient = getFTPClient(ip, port, username, password);
        if (ftpClient == null) {
            return result;
        }
        ZipOutputStream zip;
        try {
            response.reset();
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment;filename=" + new String(zipFileName.getBytes(LOCAL_CHARSET), SERVER_CHARSET));

            BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
            zip = new ZipOutputStream(out);

            for (FileEntry fileEntry: fileEntryList) {
                String fileName = fileEntry.getFileName();
                String path = fileEntry.getFilePath();
                ftpClient.changeWorkingDirectory(path);
                FTPFile[] files = ftpClient.listFiles();
                for (FTPFile file: files) {
                    if (file.getName().equals(fileName)) {
                        if (!path.endsWith("/")) {
                            path += "/";
                        }
                        if (path.startsWith("/")) {
                            path = path.substring(1);
                        }
                        zip.putNextEntry(new ZipEntry(path + fileName));
                        BufferedInputStream in = new BufferedInputStream(ftpClient.retrieveFileStream(new String(fileName.getBytes(LOCAL_CHARSET), SERVER_CHARSET)));
                        byte[] buff = new byte[1024];
                        int len;
                        while((len = in.read(buff)) != -1) {
                            zip.write(buff, 0, len);
                        }
                        zip.closeEntry();
                        in.close();
                        ftpClient.completePendingCommand();
                        break;
                    }
                }
            }
            zip.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            close(ftpClient);
        }
        return result;
    }

    /**
     * 网页直接显示ftp上的图片
     * @param ip ftp服务器的ip地址
     * @param port ftp服务器的端口
     * @param username 用户名
     * @param password 密码
     * @param response 响应对象
     * @param fileName 图片名称
     * @param serverPath ftp上的路径
     */
    public static void showImage(String ip, int port, String username, String password, HttpServletResponse response, String fileName, String serverPath) {
        FTPClient ftpClient = getFTPClient(ip, port, username, password);
        BufferedInputStream in;
        BufferedOutputStream out;
        if (ftpClient == null) {
            return;
        }
        try {
            response.setContentType("image/*");
            out = new BufferedOutputStream(response.getOutputStream());
            ftpClient.changeWorkingDirectory(serverPath);
            FTPFile[] files = ftpClient.listFiles();
            for (FTPFile file: files) {
                if (file.getName().equals(fileName)) {
                    in = new BufferedInputStream(ftpClient.retrieveFileStream(new String(file.getName().getBytes(LOCAL_CHARSET), SERVER_CHARSET)));
                    if (in == null) {
                        return;
                    }
                    byte[] buff = new byte[1024 * 10];
                    int len;
                    while((len = in.read(buff)) != -1) {
                        out.write(buff, 0, len);
                    }
                    in.close();
                    out.close();
                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            close(ftpClient);
        }
    }

    /*
    获取连接
     */
    private static FTPClient getFTPClient(String ip, int port, String username, String password) {
        FTPClient ftp = new FTPClient();
        try {
            ftp.connect(ip, port);
            ftp.login(username, password);
            int replyCode = ftp.getReplyCode();
            if (!FTPReply.isPositiveCompletion(replyCode)) {
                ftp.disconnect();
                return null;
            }
            // 开启服务器对UTF-8的支持,如果服务器支持就用UTF-8编码,否则就使用本地编码(GBK).
            int command = ftp.sendCommand("OPTS UTF8", "ON");
            if (FTPReply.isPositiveCompletion(command)) {
                LOCAL_CHARSET = "UTF-8";
            }
            //设置ftp连接超时,单位毫秒,默认是0,即无限超时
            ftp.setDataTimeout(120000);
            ftp.setControlEncoding(LOCAL_CHARSET);
            // 设置被动模式
            ftp.enterLocalPassiveMode();
            ftp.setFileType(FTP.BINARY_FILE_TYPE);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return ftp;
    }

    /*
    关闭连接
     */
    private static boolean close(FTPClient ftpClient) {
        if (ftpClient == null) {
            return false;
        }
        try {
            ftpClient.logout();
            ftpClient.disconnect();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return true;
    }

    /*
    递归删除文件夹
     */
    private static boolean removeDirectory(FTPClient ftpClient, String serverPath) {
        boolean result = true;
        try {
            FTPFile[] files = ftpClient.listFiles();
            if (files.length == 0) {
                if (serverPath.endsWith("/")) {
                    serverPath = serverPath.substring(0, serverPath.lastIndexOf("/"));
                }
                String[] paths = new String[2];
                paths[0] = serverPath.substring(0, serverPath.lastIndexOf("/"));
                paths[1] = serverPath.substring(serverPath.lastIndexOf("/") + 1);
                if (ftpClient.changeToParentDirectory()) {
                    ftpClient.removeDirectory(paths[1]);
                    if (!paths[0].isEmpty()) {
                        result = removeDirectory(ftpClient, paths[0]);
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }
}

2、controller:

注:打包压缩包下载时使用了实体类,而不是使用Map,是因为键有可能重复的情况,用实体类可以解决这一局限!

@Controller
public class UploadController {

    private static final String IP = "192.168.1.26";
    private static final int PORT = 21;
    private static final String USERNAME = "test";
    private static final String PASSWORD = "123456";

    @RequestMapping("/getUploadPage")
    public String getUploadPage() {
        return "ajax-prototype-upload";
    }

    @RequestMapping("/upload")
    @ResponseBody
    public String upload(MultipartFile[] upFiles) {
        for (MultipartFile upFile : upFiles) {
            String fileName = upFile.getOriginalFilename();
            File file = new File(fileName);
            String uploadPath = "/test/abc/";
            try {
                upFile.transferTo(file);
                FTPUtil.upload(IP, PORT, USERNAME, PASSWORD, uploadPath, file);
                //transferTo会生成一个临时文件,上传完成后需要调用delete删除此文件
                boolean b = file.delete();
                System.out.println(b);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return "success";
    }

    @RequestMapping("/download")
    public void download(HttpServletResponse response) {
        String fileName = "1.bmp";
        String downloadPath = "/test/abc/";
        FTPUtil.download(IP, PORT, USERNAME, PASSWORD, response, fileName, downloadPath);
    }

    @RequestMapping("/zipDownload")
    public void zipDownload(HttpServletResponse response) {
        String fileName = "压缩包测试.zip";
        List<FileEntry> fileEntryList = new ArrayList<>();
        FileEntry fileEntry = new FileEntry();
        fileEntry.setFileName("1.bmp");
        fileEntry.setFilePath("/test/abc/");
        fileEntryList.add(fileEntry);

        fileEntry = new FileEntry();
        fileEntry.setFileName("2.bmp");
        fileEntry.setFilePath("/test/abc/");
        fileEntryList.add(fileEntry);

        fileEntry = new FileEntry();
        fileEntry.setFileName("1.bmp");
        fileEntry.setFilePath("/test/");
        fileEntryList.add(fileEntry);

        fileEntry = new FileEntry();
        fileEntry.setFileName("1.bmp");
        fileEntry.setFilePath("/");
        fileEntryList.add(fileEntry);

        FTPUtil.zipDownload(IP, PORT, USERNAME, PASSWORD, response, fileEntryList, fileName);
    }

    @RequestMapping("/remove")
    @ResponseBody
    public String remove(@RequestParam("file") String file) {
        String serverPath = "/test/abc/";
        boolean result = FTPUtil.remove(IP, PORT, USERNAME, PASSWORD, file, serverPath);
        if (result) {
            return "success";
        } else {
            return "failed";
        }
    }

    @RequestMapping("/showImage")
    public void showImage(HttpServletResponse response) {
        String fileName = "1.bmp";
        String serverPath = "/test/";
        FTPUtil.showImage(IP, PORT, USERNAME, PASSWORD, response, fileName, serverPath);
    }
}

3、FileEntry实体类:

public class FileEntry {

    private String fileName;
    private String filePath;

    public String getFileName() {
        return fileName;
    }

    public void setFileName(String fileName) {
        this.fileName = fileName;
    }

    public String getFilePath() {
        return filePath;
    }

    public void setFilePath(String filePath) {
        this.filePath = filePath;
    }

    @Override
    public String toString() {
        return "FileEntry{" +
                "fileName='" + fileName + '\'' +
                ", filePath='" + filePath + '\'' +
                '}';
    }
}

4、html:

<html>
<head>
    <title>ajax-prototype-upload</title>
    <script src="js/jquery.js"></script>
</head>
<body id="body">
选择文件:<input id="file" type="file" name="upFiles" multiple/>
<input id="upload" type="button" value="上传"/><br/>
<input id="download" type="button" value="下载">
<button id="remove">删除</button>
<button id="zipDownload">多文件下载</button>
<button id="showImage">展示图片</button>


<script>
    $(function() {
        $("#upload").on('click', function() {
            let data = new FormData();
            for (let i = 0; i < $('#file')[0].files.length; i++) {
                data.append('upFiles', $('#file')[0].files[i]);
            }
            $.ajax({
                url: '/upload',
                method: 'POST',
                data: data,
                type: 'POST',
                dataType: 'TEXT',
                contentType: false,
                processData: false,
                success: function(msg) {
                    alert(msg);
                }
            });
        });
        $('#download').on('click', function() {
            window.location.href = "/download";
        });
        $('#zipDownload').on('click', function() {
            window.location.href = "/zipDownload";
        });
        $('#remove').on('click', function() {
            $.ajax({
                url: '/remove',
                method: 'POST',
                data: {file: '1.bmp'},
                type: 'POST',
                dataType: 'TEXT',
                success: function(msg) {
                    alert(msg);
                }
            });
        });
        $('#showImage').on('click', function() {
            $('#body').append($('<img src="/showImage"/>'));
        });

    });
</script>
</body>
</html>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值