1. 搭建FTP服务器[先在本地搭建, 测试成功后, 再在远程服务器上搭建]
* 搭建步骤: http://www.cnblogs.com/josephcnblog/articles/6929345.html
2. 导入jar包(Maven环境下, 如果这里引入补全, 请参看各个类中引入的jar包)
commons-net
commons-net
${commons.version}
commons-fileupload
commons-fileupload
1.3.1
commons-io
commons-io
2.4
3. 编写代码
* 配置文件===========================================================================
* resource.properties(静态资源文件, 里面定义了连接FTP服务器需要的参数, 以及一些参数)
# FILI_UPLOAD_PATH
FILE_UPLOAD_PATH = FTP服务器的物理路径(在搭建服务器的时候定义的)
# FTP_SERVER_IP
FTP_SERVER_IP = FTP服务器的IP地址(如果在本地搭建服务器, 就是本机的IP地址)
# FTP_SERVER_PORT
FTP_SERVER_PORT = FTP服务器的端口号(默认是21端口)
# FTP_SERVER_USERNAME
FTP_SERVER_USERNAME = FTP服务器的用户名(在搭建服务器时, 看服务器隶属于哪个用户, 就是该用户的用户名)
# FTP_SERVER_PASSWORD
FTP_SERVER_PASSWORD = FTP服务器的密码(在搭建服务器时, 看服务器隶属于哪个用户, 就是该用户的密码)
* 在spring容器(配置文件)中导入resource.properties(注意路径)
classpath:config/*.properties
* 配置文件===========================================================================
* 工具类=============================================================================
* IDUtils.java(文件上传成功之后, 生成的随机的文件名)
package com.wangzhixuan.commons.utils;
import java.util.Random;
public class IDUtils {
/**
* 生成文件名称
* @return
*/
public static String getFileName() {
//取当前时间的长整形值包含毫秒
long millis = System.currentTimeMillis();
//long millis = System.nanoTime();
//加上四位随机数
Random random = new Random();
int end3 = random.nextInt(9999);
//如果不足四位前面补0
String str = millis + String.format("%04d", end3);
return str;
}
}
* FtpUtil.java(此类是客户端连接FTP服务器的底层代码)
package com.wangzhixuan.commons.utils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
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;
/**
* FTP工具类
* @author zoumingqiao
*/
public class FtpUtil {
/**
* Description: 向FTP服务器上传文件
* @param host FTP服务器hostname
* @param port FTP服务器端口
* @param username FTP登录账号
* @param password FTP登录密码
* @param basePath FTP服务器基础目录
* @param filePath FTP服务器文件存放路径。例如分日期存放:/2015/01/01。
文件的路径为basePath+filePath
* @param filename 上传到FTP服务器上的文件名
* @param input 输入流
* @return 成功返回true,失败返回false
*/
public static boolean uploadFile(
String host, int port, String username,
String password, String basePath,
String filePath, String filename, InputStream input) {
boolean result = false;
FTPClient ftp = new FTPClient();
try {
int reply;
// 如果采用默认端口,可以使用ftp.connect(host)的方式直接连接FTP服务器
ftp.connect(host, port);// 连接FTP服务器
ftp.login(username, password);// 登录
reply = ftp.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
ftp.disconnect();
return result;
}
// 进入FTP的物理路径, 如 E:\\FTPLocalDirectory
String tempPath = basePath;
if (ftp.changeWorkingDirectory("/")) {
String[] dirs = filePath.split("/");// 如[, 2017, 06, 02]
if (dirs != null && dirs.length > 0) {
for (String dir : dirs) {
// 过滤掉空对象和空字符串
if (null == dir || "".equals(dir)) {
continue;
}
/**
* 定位到下一级目录, 如:
* E:\\FTPLocalDirectory\\2017,
* E:\\FTPLocalDirectory\\2017\\06,
* E:\\FTPLocalDirectory\\2017\\06\\02
*/
if (!ftp.changeWorkingDirectory(dir)) {// 无法定位到该目录, 说明该目录不存在
ftp.mkd(dir);// 创建下一级目录
boolean flag = ftp.changeWorkingDirectory(dir);// 定位到下一级目录
tempPath += "/" + dir;// 全路径
System.out.println("切换到目录:[ " + tempPath + " ]: " + (flag ? "成功!" : "失败!"));
}
}
}
} else {
// 如果物理路径不存在, 那么直接返回false结果
return result;
}
/*
// 如果完整的目录不存在
String tempPath = "";
System.out.println("FTP开始的物理路径: " + basePath);
if (!ftp.makeDirectory(basePath+filePath)) {
// 准备创建目录
String[] dirs = filePath.split("/");
tempPath = basePath;
for (String dir : dirs) {
// 过滤掉空对象和空字符串
if (null == dir || "".equals(dir)) continue;
// 拼凑准备创建的第一级目录
tempPath += "/" + dir;
File file = new File(tempPath);
// 如果要创建的目录不存在
if (!file.exists()) {
// 创建这个目录
boolean mkdFlag = file.mkdir();
System.out.println((mkdFlag ? "FTP的物理路径创建成功!" : "FTP的物理路径创建失败!")
+ " FTP的临时的物理路径是:" + tempPath);
//boolean ff = ftp.makeDirectory(tempPath);
}
}
}
boolean rt = ftp.changeWorkingDirectory(tempPath);
System.out.println("===================切换FTP的开始物理路径到[ "+tempPath+" ]下时: " + (rt ? "成功!" : "失败!"));
*/
//设置上传文件的类型为二进制类型[避免上传图片类型的文件时读取图片失败]
ftp.setFileType(FTP.BINARY_FILE_TYPE);
//上传文件
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) {
ioe.printStackTrace();
}
}
}
return result;
}
/**
* Description: 从FTP服务器下载文件
* @param host FTP服务器hostname
* @param port FTP服务器端口
* @param username FTP登录账号
* @param password FTP登录密码
* @param remotePath FTP服务器上的相对路径
* @param fileName 要下载的文件名
* @param localPath 下载后保存到本地的路径
* @return文件下载成功返回true, 失败返回false
*/
public static boolean downloadFile(
String host, int port, String username, String password,
String remotePath, String fileName, String localPath) {
boolean result = false;
FTPClient ftp = new FTPClient();
try {
int reply;
ftp.connect(host, port);
// 如果采用默认端口,可以使用ftp.connect(host)的方式直接连接FTP服务器
ftp.login(username, password);// 登录
reply = ftp.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
ftp.disconnect();
return result;
}
ftp.changeWorkingDirectory(remotePath);// 转移到FTP服务器目录
FTPFile[] fs = ftp.listFiles();
for (FTPFile ff : fs) {
if (ff.getName().equals(fileName)) {
File localFile = new File(localPath + "/" + ff.getName());
OutputStream is = new FileOutputStream(localFile);
ftp.retrieveFile(ff.getName(), is);
is.close();
}
}
ftp.logout();
result = true;
} catch (IOException e) {
e.printStackTrace();
} finally {
if (ftp.isConnected()) {
try {
ftp.disconnect();
} catch (IOException ioe) {
}
}
}
return result;
}
/**
* 测试
* @param args
*/
public static void main(String[] args) {
try {
FileInputStream in=new FileInputStream(new File("要上传的文件全路径"));
boolean flag = uploadFile("FTP服务器IP地址", 端口号, "用户名", "密码", "FTP服务器的物理路径","/2017/06/02(这是当天的日期)", "上传后生成的文件名", 输入流);
System.out.println(flag);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
* 工具类=============================================================================
* Service层/Controller层/JSP页面=====================================================
* IFileService.java(Service接口)
package com.wangzhixuan.service;
import org.springframework.web.multipart.MultipartFile;
/**
* 文件操作Service接口
* @author zoumingqiao
*/
public interface IFileService {
public boolean uploadFile(MultipartFile uploadFile) throws Exception;
}
* FileServiceImpl.java(Service接口实现类)
package com.wangzhixuan.service.impl;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import com.wangzhixuan.commons.utils.FtpUtil;
import com.wangzhixuan.commons.utils.IDUtils;
import com.wangzhixuan.service.IFileService;
/**
* 文件操作Service实现类
* @author zoumingqiao
*/
@Service
public class FileServiceImpl implements IFileService {
// 获取连接FTP服务器的参数(这种从配置文件中获取信息的方法很方便, 注意采用)
@Value("${FILE_UPLOAD_PATH}")
private String FILE_UPLOAD_PATH;// 服务端存放图片的基础目录(即FTP服务器的物理路径)
@Value("${FTP_SERVER_IP}")
private String FTP_SERVER_IP;// FTP服务器的IP地址
@Value("${FTP_SERVER_PORT}")
private Integer FTP_SERVER_PORT;// FTP服务器的端口号
@Value("${FTP_SERVER_USERNAME}")
private String FTP_SERVER_USERNAME;// FTP服务器的用户名
@Value("${FTP_SERVER_PASSWORD}")
private String FTP_SERVER_PASSWORD;// FTP服务器的密码
/**
* 文件上传
* @param uploadFile Controller层传递过来的多部件文件对象
*/
@Override
public boolean uploadFile(MultipartFile uploadFile) throws Exception {
// 上传文件功能实现
String path = saveFile(uploadFile);
if (StringUtils.isNotBlank(path)) {
return true;
}
return false;
}
/**
* 保存文件
* @param uploadFile要保存的文件
* @return保存成功返回true, 失败返回false
*/
private String saveFile(MultipartFile uploadFile) {
String result = null;
try {
// 上传文件功能实现
// 判断文件是否为空
if (uploadFile.isEmpty())
return null;
// 上传文件以日期为单位分开存放,可以提高图片的查询速度
String filePath = "/" + new SimpleDateFormat("yyyy").format(new Date()) + "/"
+ new SimpleDateFormat("MM").format(new Date()) + "/"
+ new SimpleDateFormat("dd").format(new Date());
// 取原始文件名
String originalFilename = uploadFile.getOriginalFilename();
// 新文件名
String newFileName = IDUtils.getFileName() + originalFilename.substring(originalFilename.lastIndexOf("."));
// 转存文件,上传到ftp服务器
boolean connectionFlag = FtpUtil.uploadFile(FTP_SERVER_IP, FTP_SERVER_PORT, FTP_SERVER_USERNAME,
FTP_SERVER_PASSWORD, FILE_UPLOAD_PATH, filePath, newFileName, uploadFile.getInputStream());
if (connectionFlag) {
result = filePath + "/" + newFileName;
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
}
* FileUpController.java(Controller层)
package com.wangzhixuan.controller;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
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 org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import com.wangzhixuan.commons.base.BaseController;
import com.wangzhixuan.service.IFileService;
@Controller
@RequestMapping("/fileup")
public class FileUpController extends BaseController{
// 注入servcie
@Autowired
private IFileService fileService;
//定位到上传单个文件界面 /fileup/goupload
@GetMapping("/goupload1")
public String goupload(){
return "admin/goupload";
}
@PostMapping("/upload")
@ResponseBody
public String upload(MultipartFile file, HttpServletRequest request) throws Exception {
// 调用Service上传文件
boolean flag = fileService.uploadFile(file);
// 文件上传成功
if (flag) {
return "{\"msg\":\"success\"}";
}
// 文件上传失败
return "{\"msg\":\"error\"}";
}
}
* goupload.jsp(页面)
function ajaxFileUpload() {
$.ajaxFileUpload ({
url: '${path}/fileup/upload', //用于文件上传的服务器端请求地址
secureuri: false, //是否需要安全协议,一般设置为false
fileElementId: 'file', //文件上传域的ID
dataType: 'json', //返回值类型 一般设置为json
success: function (data, status) {//服务器成功响应处理函数
if (data != null) {
if ("success" == data.msg) {
alert("程序下达成功!");
} else {
alert("程序下达失败!");
}
}
console.log(data.msg);
},
error: function (data, status, e) {//服务器响应失败处理函数
alert("程序下达失败!");
}
});
return false;
}