作者有一个需求,文件是存在FTP服务器中,然后在controller层写代码实现下载,可惜在其它网站上找到的都是下载到指定路径,无法实现在页面上显示下载的效果,作者经过多方查询资料整合后,终于完成功能,现分享给大家.
内容如下:
package com.foxconn.dcc.utils;
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.*;
import java.util.HashMap;
/**
* @ClassName: FtpUtil
* @Description: FTP工具类
* @Author rookie
* @date 2020/5/6 10:41
* @Version: 1.0
**/
public class FtpUtil {
/**
* FTP服务器hostname(需要修改此处)
*/
private static String HOST = "10.32.123.123";
/**
* FTP服务器端口(默认21)
*/
private static int PORT = 21;
/**
* FTP登录账号(需要修改此处)
*/
private static String USERNAME = "ftpService";
/**
* FTP登录密码(需要修改此处)
*/
private static String PASSWORD = "a123456789";
/**
* FTP服务器基础目录(不要修改此处)
*/
private static String BASEPATH = "";
/**
* FTP客户端
*/
private static FTPClient ftp;
/**
* @Description 初始化FTP客户端
* @Author rookie
* @date 2020/5/6 10:41
* @Param []
* @return boolean
**/
public static boolean initFtpClient(){
ftp = new FTPClient();
int reply;
try {
// 连接FTP服务器
ftp.connect(HOST, PORT);
//登录, 如果采用默认端口,可以使用ftp.connect(host)的方式直接连接FTP服务器
ftp.login(USERNAME, PASSWORD);
ftp.setBufferSize(10240);
//设置传输超时时间为60秒
ftp.setDataTimeout(600000);
//连接超时为60秒
ftp.setConnectTimeout(600000);
//FTP以二进制形式传输
ftp.setFileType(FTP.BINARY_FILE_TYPE);
reply = ftp.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
ftp.disconnect();
return false;
}
} catch (IOException e) {
e.printStackTrace();
}
return true;
}
/**
* Description: 向FTP服务器上传文件
* @param filePath FTP服务器文件存放路径。例如分日期存放:/2015/01/01。文件的路径为basePath+filePath
* @param filename 上传到FTP服务器上的文件名
* @param input 本地要上传的文件的 输入流
* @return 成功返回true,否则返回false
*/
public static boolean uploadFile(String filePath, String filename, InputStream input) {
boolean result = false;
try {
filePath = new String(filePath.getBytes("GBK"),"iso-8859-1");
filename = new String(filename.getBytes("GBK"),"iso-8859-1");
if (!initFtpClient()){
return result;
};
//切换到上传目录
ftp.enterLocalPassiveMode();
if (!ftp.changeWorkingDirectory(BASEPATH+filePath)) {
//如果目录不存在创建目录
String[] dirs = filePath.split("/");
String tempPath = BASEPATH;
for (String dir : dirs) {
if (null == dir || "".equals(dir)){
continue;
}
tempPath += "/" + dir;
if (!ftp.changeWorkingDirectory(tempPath)) {
if (!ftp.makeDirectory(tempPath)) {
return result;
} else {
ftp.changeWorkingDirectory(tempPath);
}
}
}
}
//设置上传文件的类型为二进制类型
ftp.setFileType(FTP.BINARY_FILE_TYPE);
//上传文件
ftp.enterLocalPassiveMode();
if (!ftp.storeFile(filename, input)) {
return result;
}
input.close();
ftp.logout();
result = true;
}
catch (IOException e) {
e.printStackTrace();
} finally {
if (ftp.isConnected()) {
try {
ftp.disconnect();
} catch (IOException ioe) {
}
}
}
return result;
}
/**
* @Description 从ftp服务器下载文件到指定输出流
* @Author andrew
* @Date 22:30 2020/3/5
* @Param [remotePath, fileName, outputStream]
* @return boolean
**/
public static boolean downloadFile(String remotePath, String fileName, OutputStream outputStream) {
boolean result = false;
try {
remotePath = new String(remotePath.getBytes("GBK"),"iso-8859-1");
fileName = new String(fileName.getBytes("GBK"),"iso-8859-1");
if (!initFtpClient()){
return result;
};
// 转移到FTP服务器目录
ftp.changeWorkingDirectory(remotePath);
ftp.enterLocalPassiveMode();
FTPFile[] fs = ftp.listFiles();
for (FTPFile ff : fs) {
if (ff.getName().equals(fileName)) {
ftp.enterLocalPassiveMode();
ftp.retrieveFile(remotePath+"/"+fileName,outputStream);
result = true;
}
}
ftp.logout();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (ftp.isConnected()) {
try {
ftp.disconnect();
} catch (IOException ioe) {
}
}
}
return result;
}
}
outputStream后面可以放在response中
package com.foxconn.dcc.controller;
import com.foxconn.dcc.utils.FtpUtil;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.HashMap;
/**
* @author rookie
* @date 2020/5/28 下午4:47
* @description: 实现下载FTP文件功能
* @modifiedBy:
*/
@Controller
@RequestMapping("/api/common/v1")
public class CommonController {
@GetMapping(value = "/file/download")
public void getFile( HttpServletResponse response,HttpServletRequest request) throws IOException {
//
// String savePath=jsonObject.getString("downloadUrl");
// String fileUniqueName=jsonObject.getString("fileUniqueName");
// String originFileName=jsonObject.getString("originFileName");
System.out.println("进来了下载");
String savePath="/rookie/dccFiles/202006";
String fileUniqueName="4559e60e-cd54-411c-bed7-8042a82f52a9.pdf";
String originFileName="原来.pdf";
CommonUtil commonUtil=new CommonUtil();
try {
//解决下载文件时 中文文件名乱码问题
boolean browserFlag = commonUtil.isMSBrowser(request);
if (browserFlag) {
//IE浏览器的乱码问题解决
originFileName = URLEncoder.encode(originFileName, "UTF-8");
} else {
//万能乱码问题解决
originFileName = new String(originFileName.getBytes("UTF-8"), "ISO-8859-1");
}
OutputStream os = new BufferedOutputStream(response.getOutputStream());
// response.setCharacterEncoding("utf-8");
response.setContentType("multipart/form-data");
response.setHeader("Content-Disposition", "attachment;fileName=" + originFileName);
FtpUtil.downloadFile(savePath, fileUniqueName, os);
os.flush();
os.close();
}catch (Exception e){
}
}
}
注意:返回参数为void,要不会报IllegalStateException的错误,即便是catch了,也是会报此错误