目录

  • 一、简介
  • 二、maven依赖
  • 三、配置类
  • 四、工具类
    • 4.1、服务器文件名中文处理
    • 4.2、下载文件名中文处理
  • 五、接口验证

一、简介

  我在之前的文章(Java实现文件上传和下载)里讲过非FTP文件的上传和下载,也讲过Java实现FTP文件上传和下载。本文主要讲通过FTP下载文件到浏览器,本文测试过程中Spring Boot 版本为2.6.0,commons-net 版本为3.8.0,JDK环境为 1.8。

二、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.6.0</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.alian</groupId><artifactId>ftp</artifactId><version>0.0.1-SNAPSHOT</version><name>ftp</name><description>java实现FTP下载文件到浏览器</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.commons</groupId><artifactId>commons-lang3</artifactId><version>3.12.0</version></dependency><dependency><groupId>commons-net</groupId><artifactId>commons-net</artifactId><version>3.8.0</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.16.14</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>compile</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

三、配置类

AppProperties.java

package com.alian.ftp.config;import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;@Data
@Component
@ConfigurationProperties(prefix = "ftp")
public class AppProperties {/*** ftp主机地址*/private String hostName;/*** ftp端口*/private int port;/*** ftp用户名*/private String userName;/*** ftp密码*/private String password;}

相关的属性配置如下:

application.yml

server:port: 8081servlet:context-path: /ftpftp:host-name: 192.168.0.151port: 21user-name: alianpassword: alian012

四、工具类

ApacheFtpUtil.java

package com.alian.ftp.utils;import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;@Slf4j
public class ApacheFtpUtil {private FTPClient ftpClient;/*** 实例化** @param hostName FTP服务器地址* @param port     FTP服务器端口* @param userName FTP登录账户* @param password FTP登录密码* @throws IOException*/public ApacheFtpUtil(String hostName, int port, String userName, String password) throws IOException {ftpClient = new FTPClient();//设置传输命令的超时ftpClient.setDefaultTimeout(20000);//毫秒//设置两个服务连接超时时间ftpClient.setConnectTimeout(10000);//毫秒//被动模式下设置数据传输的超时时间ftpClient.setDataTimeout(15000);//毫秒//连接FTPftpClient.connect(hostName, port);//更加账户密码登录服务ftpClient.login(userName, password);//被动模式ftpClient.enterLocalPassiveMode();}public Pair<Boolean, String> downloadFile(String ftpFilePath, String fileName, HttpServletResponse response) {InputStream input = null;OutputStream out = null;try {response.reset();//此处你就根据你要下载的类型去设置即可,比如我下载.avi格式的文件,可以设置response.setContentType("video/avi");response.setContentType("application/download");//解决中文不能生成文件(包含空格)response.setHeader("Content-Disposition", "attachment; filename=\"" + URLEncoder.encode(fileName,"UTF-8").replaceAll("\\+","%20")+"\"");//传输模式ftpClient.setFileTransferMode(FTP.STREAM_TRANSFER_MODE);// 设置以二进制流的方式传输ftpClient.setFileType(FTP.BINARY_FILE_TYPE);//进入目录ftpClient.changeWorkingDirectory(ftpFilePath);FTPFile[] files = ftpClient.listFiles();if (files.length < 1) {return Pair.of(false, "目录为空");}boolean fileExist = false;boolean downloadFlag = false;for (FTPFile ftpFile : files) {String ftpFileName=new String(ftpFile.getName().getBytes(StandardCharsets.ISO_8859_1),StandardCharsets.UTF_8);if (fileName.equals(ftpFileName)) {fileExist = true;input = ftpClient.retrieveFileStream(new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1));out = response.getOutputStream();int len;byte[] bytes = new byte[1024];while ((len = input.read(bytes)) != -1) {out.write(bytes, 0, len);}out.flush();downloadFlag = true;break;}}if (!fileExist) {return Pair.of(false, "FTP服务器上文件不存在");}return Pair.of(downloadFlag, downloadFlag ? "下载成功" : "下载失败");} catch (IOException e) {e.printStackTrace();return Pair.of(false, "下载文件异常");} finally {try {if (out != null) {out.close();}if (input != null) {input.close();}} catch (IOException e) {e.printStackTrace();}}}public void close() {try {if (ftpClient != null && ftpClient.isConnected()) {ftpClient.disconnect();}} catch (IOException e) {e.printStackTrace();}}}

  大致的流程:

  • 设置ContentTypeHeader
  • 设置二进制流的传输模式
  • 进入到要下载的文件的目录,获取到文件列表进行遍历
  • 如果文件存在,则通过流的方式进行文件的读写
  • 输出流刷到页面(依赖Header中的设置)

4.1、服务器文件名中文处理

  关于中文文件名编码说明:

 //设置编码(支持UTF-8字符集的操作系统)ftpClient.setAutodetectUTF8(true);

  有些小伙伴可能会去设置上面这个代码,这个就是在支持UTF-8字符集的操作系统里会自动处理中文,比如这个apache文件服务器上文件一般默认是ISO-8859-1编码,使用它就会自动变成UTF-8。但是服务器可能不支持UTF-8字符集,ftpClient.setAutodetectUTF8(true)不会生效,又会有问题,所有建议不加,那就使用下面的代码进行编码转换了。

String ftpFileName=new String(ftpFile.getName().getBytes(StandardCharsets.ISO_8859_1),StandardCharsets.UTF_8);

4.2、下载文件名中文处理

  假设下载的文件的文件名有中文时,我们就需要进行URLEncoder,下面这个就是对中文的处理,同时可以重命名文件

response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName,"UTF-8"));

  假设下载的文件的文件名有空格,可能会变成加号:+,我们可以通过替换函数进行处理:replaceAll(“\+”,“%20”),其他特殊字符看情况处理了

response.setHeader("Content-Disposition", "attachment; filename=\"" + URLEncoder.encode(fileName,"UTF-8").replaceAll("\\+","%20")+"\"");

五、接口验证

FtpController.java

package com.alian.ftp.controller;import com.alian.ftp.config.AppProperties;
import com.alian.ftp.utils.ApacheFtpClient;
import com.alian.ftp.utils.ApacheFtpUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;@Slf4j
@Controller
@RequestMapping(value = "/file")
public class FtpController {@Autowiredprivate AppProperties appProperties;@RequestMapping("download")public String downloadFtpFile(HttpServletRequest request, HttpServletResponse response) {ApacheFtpUtil ftpUtil = null;try {//http://localhost:8081/ftp/file/downloadString ftpFilePath="/icss/a2ce09b3536e57de";String fileName="20220803下载的视频.avi";log.info("文件路径:{}",ftpFilePath);log.info("文件名称:{}",fileName);ftpUtil = new ApacheFtpUtil(appProperties.getHostName(), appProperties.getPort(), appProperties.getUserName(), appProperties.getPassword());Pair<Boolean, String> pair = ftpUtil.downloadFile(ftpFilePath, fileName, response);return pair.getRight();} catch (Exception e) {log.error("下载异常",e);return "下载文件异常";} finally {if (ftpUtil != null) {ftpUtil.close();}}}
}

  请求地址:http://localhost:8081/ftp/file/download

Java实现FTP下载文件到客户端(浏览器)相关推荐

  1. 【踩坑】Linux java中ftp下载文件,解压文件损坏,以及图片下载打开只显示下载路径的问题

    [踩坑]Linux java中ftp下载文件,解压文件损坏,以及图片下载打开只显示下载路径的问题 一. 问题重现 二. 问题解决思路 1. 确认是不是上传就导致数据出错了 2. 是不是平台问题 三. ...

  2. java使用ftp下载文件到本地(只是下载)

    1.添加依赖         camel-ftp依赖与commons-net依赖两者取其中一个即可         <dependency>             <groupId ...

  3. java ftp获取文件夹大小,java 用FTPClient 下载文件时不显示总大小?解决方案

    java 用FTPClient 下载文件时不显示总大小? FTPClient ftp = new FTPClient(); ftp.setControlEncoding("utf-8&quo ...

  4. java下载的文件不完整_JAVA 解决FTP下载文件不完整问题

    在使用java的ftp下载服务器上的文件获取文件的byte[],然后对byte进行加密传输时, 注意是要获取byte[],而不是下载文件到本地: 发现下载的byte[]大小总是小于文件实际大小,并且下 ...

  5. Java 实现上传文件到FTP和从FTP下载文件

    在eclipse 中创建项目,并将commons-net-3.6.jar包复制到项目中 commons-net-3.6.jar:链接:https://pan.baidu.com/s/1iz0862TX ...

  6. ftp读取服务器文件是否存在,java读取ftp服务器文件是否存在

    java读取ftp服务器文件是否存在 内容精选 换一换 弹性云服务器通过SNAT访问公网上服务器,出现TCP建链失败的情况,可通过以下方法进行排查.执行以下命令,查看远端服务器是否开启了"t ...

  7. javaftp读取服务器文件,java读取ftp服务器文件

    java读取ftp服务器文件 内容精选 换一换 文件系统创建完成后,用户需在客户端挂载文件共享,在本地共享目录和CSG的文件共享建立映射,通过操作本地的目录实现对CSG共享目录的操作,实现数据实时上云 ...

  8. 直接读取ftp服务器文件,java读取ftp服务器文件

    java读取ftp服务器文件 [2021-02-05 07:08:30]  简介: php去除nbsp的方法:首先创建一个PHP代码示例文件:然后通过"preg_replace(" ...

  9. 使用FTP下载文件资源

    使用FTP下载文件(新手向) 1.FTP介绍 FTP是File Transfer Protocol(文件传输协议)的英文简称,而中文简称为"文件传输协议".用于Internet上的 ...

最新文章

  1. 微信AI体验中心发布上线了!
  2. vim、g++、gdb及makefile的学习
  3. 大话设计模式(四 业务的封装)
  4. 函数模板的载体-HPP
  5. P3514-[POI2011]LIZ-Lollipop【思路题】
  6. Oracle 数据库错误信息:动态执行表不可访问,本会话的自动统计被禁止
  7. Javascript、Dom、JQuery
  8. Perl正则表达式匹配
  9. SQLite3中的数据类型
  10. python繁体中文到简体中文的转换
  11. Lazy Load Plugin for jQuery延迟加载测试成功
  12. conda安装tensorflow-GPU出现CondaHTTPError: HTTP 000 CONNECTION FAILED for url错误
  13. Angr安装与使用之使用篇(二)
  14. linux机器crt连接不上,SecureCRT连不上Linux主机了,求破
  15. 使用Microsoft Office Visio 2007 绘图
  16. js文字展示各种滚动效果
  17. 学好mysql数据库能找到什么工作_MySQL数据库学习路线汇总整理全集(附详细的学习路线介绍图)...
  18. HTML基础跟着李南江学编程
  19. Python+tkinter应用程序设置背景图片
  20. 购买计算机设备计入什么科目,企业购买设备计入什么会计科目?附会计分录

热门文章

  1. Unity Texture2D的可读性问题
  2. 2021年3月PHP免费自学最全教程来了
  3. 计算机附件计算器的用法,计算机附件中计算器使用方法.doc
  4. DayDayUp:2021,再见了,无论是躺平还是内卷—愿大家改变不可接受的,接受不可改变的—心若有向往,何惧道阻且长
  5. vue简单实现词云图组件
  6. GEE5:kNDVI植被指数的获取
  7. 像FIFA一样踢球的AI,比打游戏更强吗?
  8. 大疆 IC设计校招笔试题目
  9. 刑侦 技侦 警种
  10. 确认main_arena相对libc的偏移地址