如何实现ftp的文件上传于下载
第一步准备一个ftp服务器;
最基本的ftp文件夹下应该有public的文件和private的文件,一般公开的文件是直接从浏览器中访问的,而私有的文件是必须通过ftp的方式和下载,基于此逻辑,就需要给到http网址;
第二步准备导入maven:
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
第三步导入当前代码
package com.yuxin.yijia.utils.ftp;
import org.apache.commons.io.FileUtils;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PropertiesLoaderUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class FileFtpUtil {
private String ftpIp;
private int port;
private String username;
private String password;
private String baseUrl;
private Resource resource = new ClassPathResource("yijia.properties");
private FileFtpUtil() {
//读取
try {
Properties props = PropertiesLoaderUtils.loadProperties(resource);
ftpIp = props.getProperty("ftpIp");
port = Integer.parseInt(props.getProperty("port", "21"));
username = props.getProperty("username");
password = props.getProperty("password");
baseUrl = props.getProperty("baseUrl", "/image");
} catch (Exception e) {
System.err.println("ftp配置初始化失败,原因:" + e);
e.printStackTrace();
}
}
public static FileFtpUtil getInstance() {
return Inner.instance;
}
private static class Inner {
private static final FileFtpUtil instance = new FileFtpUtil();
}
/**
* @param file 需要上传的文件
* @param filename 上传的----文件名.后缀 例:c.png 不带路径
* @param path 文件路径,如果没有此路径则会创建文件夹
* @throws IOException
*/
public boolean picreate(File file, String filename, String path) throws IOException {
//创建一个FtpClient对象
FTPClient ftpClient = new FTPClient();
//创建ftp连接,默认是:21端口
ftpClient.connect(ftpIp, port);
//登录ftp服务器,使用用户名 和密码
ftpClient.login(username, password);
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
int reply;
// 获取ftp登录应答代码
reply = ftpClient.getReplyCode();
// 验证是否登陆成功
if (!FTPReply.isPositiveCompletion(reply)) {
ftpClient.disconnect();
System.err.println("FTP server refused connection.");
}
//上传文件
//读取本地文件
FileInputStream inputStream = new FileInputStream(file);
//设置上传的路径
if (!path.startsWith("/"))
path = "/" + path;
if (!baseUrl.startsWith("/"))
baseUrl = "/" + baseUrl;
path = baseUrl + path;
// String fullpath = "ftp://" + ftpIp + ":" + port + path;
String d;
try {
//目录编码,解决中文路径问题
d = new String(path.toString().getBytes("GBK"), "iso-8859-1");
//尝试切入目录
if (!ftpClient.changeWorkingDirectory(d)) {
String[] arr = path.split("/");
StringBuffer sbfDir = new StringBuffer();
//循环生成子目录
for (String s : arr) {
if (s == null || s.trim().equals(""))
continue;
sbfDir.append("/");
sbfDir.append(s);
//目录编码,解决中文路径问题
d = new String(sbfDir.toString().getBytes("GBK"), "iso-8859-1");
//尝试切入目录
if (ftpClient.changeWorkingDirectory(d))
continue;
if (!ftpClient.makeDirectory(d)) {
System.out.println("[失败]ftp创建目录:" + sbfDir.toString());
ftpClient.logout();
return false;
}
System.out.println("[成功]创建ftp目录:" + sbfDir.toString());
}
//将目录切换至指定路径
if (!ftpClient.changeWorkingDirectory(d)) {//切换到指定目录
ftpClient.logout();
return false;
}
}
} catch (Exception e) {
e.printStackTrace();
ftpClient.logout();
return false;
}
//修改上传文件的格式
//第一个参数:服务器端文档名
//第二个参数:上传文档的inputStream
boolean res = ftpClient.storeFile(filename, inputStream);
System.out.println("上传文件" + filename + ":" + res);
//关闭连接
ftpClient.logout();
return true;
}
/**
* @param httpUrl 文件的网络地址,请确定是上传到ftp上的文件
* @return
*/
public boolean del4Http(String httpUrl) throws IOException {
//创建一个FtpClient对象
FTPClient ftpClient = new FTPClient();
//创建ftp连接,默认是:21端口
ftpClient.connect(ftpIp, port);
//登录ftp服务器,使用用户名 和密码
ftpClient.login(username, password);
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
int reply;
// 获取ftp登录应答代码
reply = ftpClient.getReplyCode();
// 验证是否登陆成功
if (!FTPReply.isPositiveCompletion(reply)) {
ftpClient.disconnect();
System.err.println("FTP server refused connection.");
}
//设置上传的路径
if (!httpUrl.startsWith("http"))
return false;
String filePath = httpUrl.substring(httpUrl.indexOf(baseUrl));
if (!baseUrl.startsWith("/"))
baseUrl = "/" + baseUrl;
int index = filePath.lastIndexOf("/");
if (index == -1) {
System.err.println("文件路径异常:" + filePath);
ftpClient.logout();
return false;
}
String path = filePath.substring(0, index);
System.out.println(path);
if (!ftpClient.changeWorkingDirectory(path)) {//切换到指定目录
System.err.println("文件路径不存在:" + filePath);
ftpClient.logout();
return false;
}
System.out.println(filePath.substring(index + 1));
if (!ftpClient.deleteFile(filePath.substring(index + 1))) {
System.err.println("文件删除失败:" + filePath);
ftpClient.logout();
return false;
}
ftpClient.logout();
System.err.println("文件已删除:" + filePath);
return true;
}
public File download4Http(String httpUrl) throws IOException {
//创建一个FtpClient对象
FTPClient ftpClient = new FTPClient();
//创建ftp连接,默认是:21端口
ftpClient.connect(ftpIp, port);
//登录ftp服务器,使用用户名 和密码
ftpClient.login(username, password);
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
int reply;
// 获取ftp登录应答代码
reply = ftpClient.getReplyCode();
// 验证是否登陆成功
if (!FTPReply.isPositiveCompletion(reply)) {
ftpClient.disconnect();
System.err.println("FTP server refused connection.");
}
if (!baseUrl.startsWith("/"))
baseUrl = "/" + baseUrl;
//设置上传的路径
// if (!httpUrl.startsWith("http"))
// return null;
int i = httpUrl.indexOf(baseUrl);
//如果上传路径中没有baseUrl,则应该是相对路径,则追加baseUrl
String filePath = null;
if (i == -1) {
filePath = baseUrl + httpUrl;
} else {
filePath = httpUrl.substring(i);
}
int index = filePath.lastIndexOf("/");
if (index == -1) {
System.err.println("文件路径异常:" + filePath);
ftpClient.logout();
ftpClient.disconnect();
return null;
}
String path = filePath.substring(0, index);
System.out.println(path);
if (!ftpClient.changeWorkingDirectory(path)) {//切换到指定目录
System.err.println("文件路径不存在:" + filePath);
ftpClient.logout();
ftpClient.disconnect();
return null;
}
String name = filePath.substring(index + 1);
System.out.println(name);
File file = new File(filePath.substring(index + 1));
if (ftpClient.retrieveFile(name, FileUtils.openOutputStream(file))) {
System.out.println("文件下载成功:" + path + ",length:" + file.length());
ftpClient.logout();
ftpClient.disconnect();
return file;
} else {
System.out.println("文件下载失败:" + path);
ftpClient.logout();
ftpClient.disconnect();
return file;
}
// ftpClient.enterLocalPassiveMode(); // 设置被动模式,开通一个端口来传输数据
}
/**
* 删除那种
*
* @param filePath
* @return
* @throws IOException
*/
public boolean del(String filePath) throws IOException {
//创建一个FtpClient对象
FTPClient ftpClient = new FTPClient();
//创建ftp连接,默认是:21端口
ftpClient.connect(ftpIp, port);
//登录ftp服务器,使用用户名 和密码
ftpClient.login(username, password);
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
int reply;
// 获取ftp登录应答代码
reply = ftpClient.getReplyCode();
// 验证是否登陆成功
if (!FTPReply.isPositiveCompletion(reply)) {
ftpClient.disconnect();
System.err.println("FTP server refused connection.");
}
//设置上传的路径
if (!filePath.startsWith("/"))
filePath = "/" + filePath;
if (!baseUrl.startsWith("/"))
baseUrl = "/" + baseUrl;
filePath = baseUrl + filePath;
int index = filePath.lastIndexOf("/");
if (index == -1) {
System.err.println("文件路径异常:" + filePath);
ftpClient.logout();
return false;
}
String path = filePath.substring(0, index);
System.out.println(path);
if (!ftpClient.changeWorkingDirectory(path)) {//切换到指定目录
System.err.println("文件路径不存在:" + filePath);
ftpClient.logout();
return false;
}
System.out.println(filePath.substring(index + 1));
if (!ftpClient.deleteFile(filePath.substring(index + 1))) {
System.err.println("文件删除失败:" + filePath);
ftpClient.logout();
return false;
}
ftpClient.logout();
System.err.println("文件已删除:" + filePath);
return true;
}
/**
* 判断某个文件(不是文件夹)存在吗
*
* @param filePath 文件或者文件夹路径
* @return
*/
public boolean isExit(String filePath) throws IOException {
//创建一个FtpClient对象
FTPClient ftpClient = new FTPClient();
//创建ftp连接,默认是:21端口
ftpClient.connect(ftpIp, port);
//登录ftp服务器,使用用户名 和密码
ftpClient.login(username, password);
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
int reply;
// 获取ftp登录应答代码
reply = ftpClient.getReplyCode();
// 验证是否登陆成功
if (!FTPReply.isPositiveCompletion(reply)) {
ftpClient.disconnect();
System.err.println("连接FTP SERVER失败,SERVER IP[" + ftpIp + port + "], Ftp response:" + ftpClient.getReplyString());
return false;
}
//设置上传的路径
if (!filePath.startsWith("/"))
filePath = "/" + filePath;
if (!baseUrl.startsWith("/"))
baseUrl = "/" + baseUrl;
filePath = baseUrl + filePath;
InputStream inputStream = ftpClient.retrieveFileStream(filePath);
if (inputStream == null || ftpClient.getReplyCode() == 550) {
System.out.println("FTP SERVER上未找到以下文件[" + filePath + "]");
return false;
}
ftpClient.logout();
return true;
}
public static void main(String[] args) {
// try {
// FileFtpUtil.picreate(new File("D:\\360MoveData\\Users\\sz\\Pictures\\Saved Pictures\\改革办平台整理2.png"), "/qinglu/888/fff.png");
// } catch (IOException e) {
// e.printStackTrace();
// }
FileFtpUtil ftp = new FileFtpUtil();
// try {
// ftp.del("/course/48996/20191111/0b16f709-1c5e-4b1d-a096-ad13b20c1f1b.jpg");
// } catch (IOException e) {
// e.printStackTrace();
// }
try {
File file = ftp.download4Http("http://192.168.0.115/image/temp/48996/20191114/e3792e70-44e6-484b-a0f7-0690527f5185.jpg");
System.out.println(file.length());
} catch (IOException e) {
e.printStackTrace();
}
// try {
// System.out.println(ftp.del4Http(path));
// } catch (IOException e) {
// e.printStackTrace();
// }
//
// String sub = path.substring(path.indexOf("/image"));
// System.out.println(sub);
}
}
第四步:在Controller中调用此静态方法
package com.yuxin.yijia.controller;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.yuxin.wx.util.ToolStr;
import com.yuxin.wx.utils.FileUtil;
import com.yuxin.wx.utils.PropertiesUtil;
import com.yuxin.wx.utils.WebUtils;
import com.yuxin.yijia.utils.ftp.FileFtpUtil;
import com.yuxin.yijia.utils.rest.ResultJson;
import org.apache.commons.lang.ArrayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartRequest;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
@Controller
public class FileController {
public static final String base = "/fileupload";
public static final String save = base + "/save";
public static final String up = base + "/up";
public static final String del = base + "/del";
public static final String get = base + "/get";
@Autowired
private PropertiesUtil propertiesUtil;
/**
* 实现删除旧的图片上传新的图片,而且还要保证其原子性,不考虑网络连接不稳定的情况(因为解决不了)
*
* @param multiPartRquest 上传的文件内容
* @param module 该文件对应的模块(根据其找到文件的前缀)
* @param oldPath 需要删除的文件,如果有路径的话携带路径
* @return
*/
@ResponseBody
@RequestMapping(value = up, method = RequestMethod.POST)
public JSONObject upPic(MultipartRequest multiPartRquest, String module, String oldPath) throws IOException {
boolean flag = false;
//先看看是不是真的有原来的文件
try {
if (ToolStr.isEmpty(oldPath)) {
return ResultJson.of(4000, "请传入原图片地址");
}
String basepath = propertiesUtil.getImageServicePath();
int basepathIndex = oldPath.indexOf(basepath);
oldPath = oldPath.substring(basepathIndex + basepath.length());
if (FileFtpUtil.getInstance().isExit(oldPath)) {
flag = true;
}
} catch (IOException e) {
e.printStackTrace();
}
//监控一下是不是只有一个文件
if (multiPartRquest.getFileMap().size() > 1) {
return ResultJson.of(4000, "只能上传1个文件");
}
// System.out.println(multiPartRquest.getMultiFileMap().size());
// System.out.println(multiPartRquest.getFileMap().size());
if (flag) {
flag = false;
//如果是有则开始进行文件上传
JSONObject res = null;
try {
res = uploadFile(multiPartRquest, getPrefix(module));
if (res.getInteger("code") == 200) {
flag = true;
}
} catch (IOException e) {
e.printStackTrace();
}
//文件上传成功后则执行删除 oldPath
if (flag) {
flag = false;
try {
if (FileFtpUtil.getInstance().del(oldPath)) {
flag = true;
return res;
} else {
System.err.println("FTP:删除文件" + oldPath + "异常");
return res;
}
} catch (IOException e) {
e.printStackTrace();
}
if (!flag) {
//如果删除失败则需要再删除新上传的图片
JSONObject data = res.getJSONObject("data");
if (data != null) {
String url = data.getString("url");
if (url != null) {
boolean ok = FileFtpUtil.getInstance().del(url);//删除新上传的文件
if (ok) {
return ResultJson.of(4002, "文件上传成功后删除失败,已成功回滚");
} else {
return ResultJson.of(4002, "文件上传成功后删除失败,回滚失败,新文件已上传");
}
}
}
return ResultJson.of(4002, "文件上传成功后删除失败,回滚失败,新文件已上传");
} else {
return res;
}
} else {
return ResultJson.of(4001, "文件上传异常");
}
// return ResultJson.of(4001, "文件上传异常");
} else {
return ResultJson.of(4000, "oldPath不存在");
}
}
/**
* 获取前缀
*
* @param module
*/
private String getPrefix(String module) {
if (ToolStr.isEmpty(module)) {
module = FileUtil.Module.TEMP;
}
return FileUtil.getPath(module, WebUtils.getCurrentCompanyId().toString());
}
/**
* FTP上传图片,保存图片
*
* @param multiPartRquest 上传的文件
* @param module (分类)模块名称参考下面的类,如果传空默认是temp类型
* @return
* @see FileUtil.Module
*/
@ResponseBody
@RequestMapping(value = save, method = RequestMethod.POST)
public JSONObject queryPic(MultipartRequest multiPartRquest, String module) {
if (ToolStr.isEmpty(module)) {
module = FileUtil.Module.TEMP;
}
String path = FileUtil.getPath(module, WebUtils.getCurrentCompanyId().toString());
// String contentType = mfile.getContentType();
// String checkExcelFileType = checkExcelFileType(contentType);
try {
return uploadFile(multiPartRquest, path);
} catch (IOException e) {
e.printStackTrace();
return ResultJson.of(4000, "文件上传异常");
}
}
public static final String[] File_Type = {"default", "xlsx", "xls", "doc", "docx", "ppt", "pptx", "pdf", "txt", "zip", "rar", "png", "jpg", "jpeg",
"3gp", "avi", "flv", "mp4", "mkv", "mov", "ogg", "wmv", "gif", "del", "", "", "", "", ""};
/**
* 文件类型是不是对应的文件
*
* @param contentType
* @return
*/
// 判断文件类型
public static boolean checkFileType(String contentType) {
int a = contentType.indexOf(".");
if (a != -1) {
return ArrayUtils.contains(File_Type, contentType);
} else {
String str = contentType.substring(a, contentType.length());
return ArrayUtils.contains(File_Type, str);
}
}
// 判断文件类型
public static String checkExcelFileType(String contentType) {
switch (contentType) {
case "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":
return ".xlsx";
case "application/vnd.ms-excel":
return ".xls";
case "application/msword":
return ".doc";
case "application/vnd.openxmlformats-officedocument.wordprocessingml.document":
return ".docx";
case "application/pdf":
return ".pdf";
case "text/plain":
return ".txt";
case "application/zip":
return ".zip";
case "application/octet-stream":
return ".rar";
case "application/x-png":
return ".png";
case "image/png":
return ".png";
case "application/x-jpg":
return ".jpg";
case "image/jpeg":
return ".jpeg";
case "video/3gpp":
return ".3gp";
case "video/x-msvideo":
return ".avi";
case "video/x-flv":
return ".flv";
case "video/mp4":
return ".mp4";
case "video/x-matroska":
return ".mkv";
case "video/quicktime":
return ".mov";
case "video/x-theora+ogg":
return ".ogg";
case "video/x-ms-wmv":
return ".wmv";
case "image/gif":
return ".gif";
}
return "";
}
/**
* 实现文件上传到ftp
*
* @param multiPartRquest 携带文件的对象
* @param prefix 文件的路径(前缀)
* @return
* @throws IOException
*/
private JSONObject uploadFile(MultipartRequest multiPartRquest, String prefix) throws IOException {
JSONObject data = new JSONObject();
JSONArray arr = new JSONArray();
Iterator iter = multiPartRquest.getFileNames();
while (iter.hasNext()) {
MultipartFile multipartFile = multiPartRquest.getFile(iter.next().toString());
// MultipartFile multipartFile = multiPartRquest.getFile("imgData");
//被注释掉的是老的使用方式
// String realPath = null;
// realPath = FileUtil.upload(multipartFile, "temp", WebUtils.getCurrentCompanyId()+"");
//通过ftp方式上传图片或者文件
String fileName = FileUtil.generateFileName(multipartFile.getOriginalFilename());
if (checkFileType(fileName)) {
return ResultJson.of(4001, "文件类型异常");
}
File file = new File(fileName);
// file = File.createTempFile("/qinglu/a/", ".jpg");
multipartFile.transferTo(file);
FileFtpUtil.getInstance().picreate(file, fileName, prefix);
// FileFtpUtil.picreate(multipartFile.getInputStream(), path + fileName);
file.deleteOnExit();//程序退出时删除临时文件
//上传文件
// req.getSession().setAttribute("imgData", multipartFile);
String url = "/" + prefix + fileName;
arr.add(url);
}
if (arr.size() == 0) {
return ResultJson.of(4000, "没有任何文件上传");
}
//判断是不是一个文件
if (arr.size() == 1) {
data.put("url", arr.get(0));
} else {
//如果是多个文件放到list中
data.put("list", arr);
}
return ResultJson.of(200, data);
}
}
如此即可实现上传和下载