Java: 在线浏览FTP服务器中的文件

来自

需要在浏览器中给用户展示远程FTP服务器中的PDF文件(此处仅针对PDF文件,其余文件实现方式类似).

需要注意的地方

  1. 一定要登录!一定要登录!一定要登录! 不登录不会提示报错,也不提示成功,就因为这个问题搞了一下午…
  2. 如果FTP文件路径包含中文,一定要转码!(代码里面会有)
  3. 编码问题,只能自己多试试了.一不小心就乱码了…
  4. 我是把FTP服务器搭建在Windows系统上,模拟了一个中文文件夹和PDF文件.使用的Windows当前登录用户的用户名和密码登录的FTP服务器.(关于Windows安装FTP服务器,请自行搜之)安装好之后,可以通过文件资源管理器,访问: ftp://127.0.0.1 或者ftp://localhost 用Windows当前登录用户的用户名和密码登录一下试试.

java标志
image-2777

依赖

依赖以下jar文件,Maven(pom.xml):

        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.9</version>
        </dependency>
        <dependency>
            <groupId>commons-net</groupId>
            <artifactId>commons-net</artifactId>
            <version>3.6</version>
        </dependency>

源码

Spring Boot项目,只有以下两个文件有修改(可以使用官网的生成器,生成代码之后,修改下面两部分代码即可).

Maven(pom.xml):

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>spring-boot-template-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-boot-template-demo</name>
    <packaging>jar</packaging>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.9</version>
        </dependency>
        <dependency>
            <groupId>commons-net</groupId>
            <artifactId>commons-net</artifactId>
            <version>3.6</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

Java:

package com.example.springboottemplatedemo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.apache.commons.net.ftp.FTPReply;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;

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

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.Arrays;


@SpringBootApplication
@Controller
public class SpringBootTemplateDemoApplication {


    public void loggerdebug(String msg) {
        System.out.println(msg);
    }


    /**
     * 使用FtpClient访问Ftp服务器上的PDF文件
     *
     * 注意: 用户名和密码不能为空,如果是Windows上搭建的FTP服务器,这里的用户名密码可以是Windows系统用户的用户名和密码.
     *
     *
     * 访问示例: http://localhost:8080/showFTPFile?ftpFileUrl=ftp://127.0.0.1/20190820/%E4%B8%AD%E6%96%87%E6%B5%8B%E8%AF%95/123456/622845.pdf&username=usftp&password=uspwd
     * 
     * url参数说明:
     *      ftpFileUrl: 文件ftp地址,参考: ftp://127.0.0.1/20190820/中文测试/123456/622845.pdf
     *      decode: 是否需要后台解码,如果传过来的路径是js编码了的,需要解码,参考: decode=1
     *      username: ftp服务器的用户名,不能为空!
     *      password: ftp服务器的密码,不能为空!
     *      download: 如果包含此参数则下载pdf文件,反之则在浏览器中查看(仅支持现代化浏览器!)
     *
     *
     * @param request
     * @param response
     * @throws IOException
     */
    @RequestMapping("/showFTPFile")
    public void showFTPFile(HttpServletRequest request, HttpServletResponse response) throws IOException {
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        String ftpFileUrl = request.getParameter("ftpFileUrl");
        String decode = request.getParameter("decode");
        String ftpUserName = request.getParameter("username");
        String ftpPassword = request.getParameter("password");
        if (StringUtils.isEmpty(ftpUserName) || StringUtils.isEmpty(ftpPassword)) {
            try (ServletOutputStream outputStream = response.getOutputStream()) {
                outputStream.write("用户名和密码不能为空!".getBytes());
                outputStream.flush();
            }
            return;
        }
        String download = request.getParameter("download");
        if (StringUtils.hasText(ftpFileUrl) && ftpFileUrl.startsWith("ftp://")) {
            if (StringUtils.hasText(decode)) {
                ftpFileUrl = URLDecoder.decode(ftpFileUrl, "GB2312");
            }
            ftpFileUrl = ftpFileUrl.replaceAll("ftp://", "");
            String server = ftpFileUrl.substring(0, ftpFileUrl.indexOf("/"));
            String fileName = new String(ftpFileUrl.replaceAll(server, ".").getBytes("GBK"), "iso-8859-1");

            FTPClient ftpClient = new FTPClient();
            try (ServletOutputStream outputStream = response.getOutputStream()) {
                ftpClient.connect(server);
                boolean loginCheck=ftpClient.login(ftpUserName, ftpPassword);
                if(!loginCheck){
                    try (ServletOutputStream outputStream = response.getOutputStream()) {
                        outputStream.write("登录失败,请检查用户名或密码是否正确!".getBytes());
                        outputStream.flush();
                    }
                    return;
                }
                int replyCode = ftpClient.getReplyCode();
                ftpClient.setDataTimeout(120000);
                ftpClient.setControlEncoding("UTF-8");
                ftpClient.setFileType(FTP.BINARY_FILE_TYPE);


                if (!FTPReply.isPositiveCompletion(replyCode)) {
                    ftpClient.disconnect();
                    loggerdebug("FTP连接失败");
                } else {
                    loggerdebug("FTP连接成功");
                }

                String contentType = "application/pdf";
                response.setContentType(contentType);


                response.reset();


                if (StringUtils.hasText(download)) {
                    // 下载文件.
                    response.addHeader("Content-Disposition", "attachment;filename=report.pdf");
                } else {
                    // 在线显示文件.
                    response.setHeader("Content-Disposition", "inline;fileName=report.pdf");
                }

                ftpClient.retrieveFile(fileName, outputStream);
                outputStream.flush();
            } finally {
                if (ftpClient.isConnected()) {
                    try {
                        ftpClient.logout();
                        ftpClient.disconnect();
                    } catch (IOException ioe) {
                        // do nothing
                    }
                }
            }
        }
    }


    public static void main(String[] args) {
        SpringApplication.run(SpringBootTemplateDemoApplication.class, args);
    }

}

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据