1. MVC从FTP服务器中上传下载文件
1.1 FTPUtil
这里给大家推荐一个FTP文件处理的工具类(自己写的,可以作参考)注:其中有部分需要spring的环境,可根据需要修改
package com.dream.demo.utils;
import lombok.Getter;
import org.apache.commons.io.IOUtils;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.util.List;
import java.util.UUID;
/*
* FTP工具类
*/
@Component
@Getter
public class FTPUtil {
// FTP服务器hostname
private static String host;
// FTP服务器端口
private static int port;
// FTP登录账号
private static String username;
// FTP登录密码
private static String password;
// FTP服务器基础目录
private static String ftpPath;
// 文件存在的临时文件夹路径
private static String lsPath;
@Value("${ftp.lsPath}")
public void setTxPath(String lsPath) {
FTPUtil.lsPath = lsPath;
}
@Value("${ftp.server.ip}")
public void setHost(String ip) {
FTPUtil.host = ip;
}
@Value("${ftp.server.port}")
public void setPort(int port) {
FTPUtil.port = port;
}
@Value("${ftp.username}")
public void setUsername(String username) {
FTPUtil.username = username;
}
@Value("${ftp.password}")
public void setPassword(String password) {
FTPUtil.password = password;
}
@Value("${ftp.ftpPath}")
public void setFtpPath(String ftpPath) {
FTPUtil.ftpPath = ftpPath;
}
/**
* 获取ftp客户端
* @return ftp
* @throws IOException io异常
*/
public static FTPClient getFTPClient() throws IOException {
FTPClient ftp = new FTPClient();
int reply;
ftp.connect(host, port);
// 如果采用默认端口,可以使用ftp.connect(host)的方式直接连接FTP服务器
ftp.login(username, password);// 登录
reply = ftp.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
//登录失败
ftp.disconnect();
return null;
}
ftp.enterLocalPassiveMode();// 设置被动模式
return ftp;
}
/**
* Description: 向FTP服务器上传文件
* @param fileSuffix 文件后缀
* @param input 输入流
* @return 成功返回true,否则返回false
*/
public static String uploadFile(FTPClient ftp,String fileSuffix, InputStream input) throws IOException {
if (ftp==null||input==null){
return null;
}
try {
//切换到上传目录
if (!ftp.changeWorkingDirectory(ftpPath+lsPath)) {
//如果目录不存在创建目录
String[] dirs = lsPath.split("/");
String tempPath = ftpPath;
for (String dir : dirs) {
if (null == dir || "".equals(dir)) continue;
tempPath += "/" + dir;
if (!ftp.changeWorkingDirectory(tempPath)) {
if (!ftp.makeDirectory(tempPath)) {
return null;
} else {
ftp.changeWorkingDirectory(tempPath);
}
}
}
}
ftp.enterLocalPassiveMode();// 设置被动模式
//设置上传文件的类型为二进制类型
ftp.setFileType(FTP.BINARY_FILE_TYPE);
//将名字覆盖掉
String filename = UUID.randomUUID().toString()+fileSuffix;
//上传文件
if (ftp.storeFile(filename, input)) {
return filename;
}
}finally {
input.close();
}
return null;
}
/**
* Description: 从FTP服务器下载单个文件
*/
public static byte[] downloadFile(FTPClient ftp,String filepath) throws IOException {
if (ftp==null){
return null;
}
InputStream inputStream = null;
try {
inputStream = ftp.retrieveFileStream(ftpPath+filepath);
return IOUtils.toByteArray(inputStream);
}finally {
if (inputStream!=null){
inputStream.close();
}
}
}
/**
* 批量删除临时文件夹中的文件
* @param filePaths 文件路径集合
* @return bool
* @throws IOException 异常
*/
public static boolean deleteFiles(FTPClient ftp,List<String> filePaths) throws IOException {
if (ftp!=null&&filePaths!=null&&filePaths.size()>0){
for (String path : filePaths) {
ftp.deleteFile(ftpPath + lsPath + "/" + path);
}
}
return true;
}
/**
* 批量删除文件
* @param filePaths 文件路径集合
* @return bool
* @throws IOException 异常
*/
public static boolean deleteFileByPath(FTPClient ftp,List<String> filePaths) throws IOException {
if (ftp!=null&&filePaths!=null&&filePaths.size()>0){
for (String path : filePaths) {
ftp.deleteFile(ftpPath+path);
}
}
return true;
}
/**
* 移动文件
* @param filePath 文件路径名
* @param folder 文件夹
* @return bool
*/
public static boolean moveFiles(FTPClient ftp,String filePath ,String folder) throws IOException {
return ftp.rename(ftpPath + lsPath +"/"+ filePath, ftpPath + folder +"/"+ filePath);
}
/**
* 关闭ftp服务器
* @param ftp ftp
* @throws IOException 异常
*/
public static void closeFTP(FTPClient ftp) throws IOException {
if (ftp != null && ftp.isConnected()) {
ftp.logout();
ftp.disconnect();
}
}
}
1.2 spring对FTPUtil的支持
config.properties
#ftp config
ftp.server.ip=192.168.***.***
ftp.server.port=**
ftp.username=
ftp.password=
ftp.ftpPath=/zuihaode/shuoshuo
ftp.lsPath=/lingshi
ftp.zsPath=/zhengshi
<!--加载配置文件,加载进来就可以通过@Value注解来获取属性的值-->
<context:property-placeholder location="classpath:config.properties" />
这里就不详细叙述,有需要的可以参考去前面的文章。
1.3 MVC业务层操作
这里提供一些简单的service层方法示例,注:一个业务操作只能有一个FTPClient。
/**
* 文件上传
* @param multipartFile 文件
*/
@Override
public String uploadFile(MultipartFile multipartFile) throws IOException {
String originalFilename = multipartFile.getOriginalFilename();
int i = originalFilename.lastIndexOf('.');
//文件后缀
String fileSuffix = originalFilename.substring(i);
FTPClient ftp = null;
try {
ftp = FTPUtil.getFTPClient();
if (ftp == null) {
//说明连接失败
logger.error("[FileServiceImpl.uploadFile]执行getFTPClient 出错:ftp连接失败");
return null;
}
//这里是返回在ftp的文件名
return FTPUtil.uploadFile(ftp, fileSuffix, multipartFile.getInputStream());
} finally {
FTPUtil.closeFTP(ftp);
}
}
/**
* 删除文件
* @param deleteFileNames 文件相对路径数组
*/
@Override
public int deleteFiles(List<String> deleteFileNames) throws IOException {
if (deleteFileNames == null) {
//没有删除的文件
return 0;
}
FTPClient ftp = null;
try {
ftp = FTPUtil.getFTPClient();
if (ftp == null) {
//说明连接失败
logger.error("[FileServiceImpl.deleteFiles]执行getFTPClient 出错:ftp连接失败");
return 0;
}
if (FTPUtil.deleteFiles(ftp, deleteFileNames)) {
return 1;
}
} finally {
FTPUtil.closeFTP(ftp);
}
return 0;
}
/**
* 下载文件
* @param filepath 文件相对路径
* @return 数据
*/
@Override
public byte[] downloadFile(String filepath) throws IOException {
FTPClient ftp = null;
try {
ftp = FTPUtil.getFTPClient();
if (ftp == null) {
//说明连接失败
logger.error("[FileServiceImpl.downloadFile]执行getFTPClient 出错:ftp连接失败");
return null;
}
return FTPUtil.downloadFile(ftp, filepath);
} finally {
FTPUtil.closeFTP(ftp);
}
}
1.4 Controller的下载和上传
上传
/**
* 单独的文件上传接口,将上传到临时文件夹
* @return 1-表示上传成功
*/
@RequestMapping (value = "/upload.action",produces = "application/json;charset=utf-8")
@ResponseBody
public Result<String> upload(HttpServletRequest request) throws IOException {
MultipartFile multipartFile = null;
if (ServletFileUpload.isMultipartContent(request)){
//有文件上传
MultipartHttpServletRequest multipartRequest = WebUtils.getNativeRequest(request, MultipartHttpServletRequest.class);
multipartFile = multipartRequest.getFile("file");
}
if (multipartFile!=null){
return Result.success(fileService.uploadFile(multipartFile));
}
return null;
}
下载
/**
* 下载文件
* @param fileXH 文件的序号
* @param djpc 登记批次
* @param response 响应
* @throws IOException 异常
*/
@RequestMapping("/download.action")
public void downloadFile(@RequestParam("fileXH") String fileXH,
@RequestParam("djpc") String djpc,
HttpServletResponse response) throws IOException {
//根据路径得到文件数据和信息
CkJz ckJz = ckJzService.selectCkjz(djpc,fileXH);
if (ckJz==null){
return;
}
//根据文件在ftp中的名称和路径获得文件数据
byte[] data = fileService.downloadFile(ckJz.getPath());
String fileName = URLEncoder.encode(ckJz.getWjmc(), "UTF-8");
OutputStream out = null;
try {
response.reset();
response.setContentType("application/octet-stream; charset=utf-8");
response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
out = response.getOutputStream();
out.write(data);
out.flush();
} finally {
if (out != null) {
out.close();
}
}
}
注:部分代码和功能与系统整体业务相关,大致流程仅供参考
2. 拓展:文件上传的控件plupload
注意引入对应的包
<script type="text/javascript" src="../js/plupload.full.min.js"></script>
完成一个简单的上传
//创建一个文件上传的对象
var uploader = new plupload.Uploader({
browse_button: 'uploadFile', //这里绑定的是一个控件的id,点击这个控件时,会触发文件上传
url: fileUrl,
max_file_size:'10mb',
filters: [ //文件类型限制
{title: "文件", extensions: "pdf,doc,docx" },
],
});
//上传文件控件初始化
uploader.init();
//绑定文件添加进队列事件
uploader.bind('FilesAdded', function (uploader, files) {
if (fileNum+uploader.files.length<=5){
//文件最多上传五个
uploader.start() //start方法执行才表示文件开始上传
}else {
layer.msg('最多保存五个文件!', {icon: 0, time: 2000, zIndex: 100});
return false;
}
});
//当队列中的某一个文件正要开始上传前触发监听函数参数
uploader.bind("BeforeUpload",function (uploader,file) {
});
//会在文件上传过程中不断触发,可以用此事件来显示上传进度监听函数参数
uploader.bind('UploadProgress', function (uploader, file) {
//uploader为当前的plupload实例对象,file为触发此事件的文件对象
});
//当队列中的某一个文件上传完成后触发监听函数参数
uploader.bind("FileUploaded",function (uploader,file,responseObject) {
//uploader为当前的plupload实例对象,file为触发此事件的文件对象,responseObject为服务器返回的信息对象,它有以下3个属性:
//response:服务器返回的文本
//responseHeaders:服务器返回的头信息
//status:服务器返回的http状态码,比如200
});