SSM使用FTP服务器上传文件[Windows Server 2008 R2虚拟系统下]

1. 搭建FTP服务器[先在本地搭建, 测试成功后, 再在远程服务器上搭建]
* 搭建步骤: http://www.cnblogs.com/josephcnblog/articles/6929345.html

2. 导入jar包(Maven环境下, 如果这里引入补全, 请参看各个类中引入的jar包)

    <!-- commons-net -->
	<dependency>
	    <groupId>commons-net</groupId>
	    <artifactId>commons-net</artifactId>
	    <version>${commons.version}</version>
	</dependency>
	<!-- 文件上传所依赖的jar包 commons-fileupload commons-io-->
	<dependency>
		<groupId>commons-fileupload</groupId>
		<artifactId>commons-fileupload</artifactId>
		<version>1.3.1</version>
	</dependency>
	<dependency>
		<groupId>commons-io</groupId>
		<artifactId>commons-io</artifactId>
		<version>2.4</version>
	</dependency>

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(注意路径)

		<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
	        <property name="locations">
	            <list>
	                <value>classpath:config/*.properties</value>
	            </list>
	        </property>
	    </bean>

* 配置文件===========================================================================

* 工具类=============================================================================
* 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(页面)

	<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
	<!DOCTYPE html>
	<html>
	<head>
	<script type="text/javascript" src="${staticPath }/static/ajaxfileupload.js" charset="utf-8"></script>
	<script type="application/javascript">

	    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;
	    }
	</script>
	</head>
	<body>
		<h1>程序下达</h1>
		<div action="${pageContext.request.contextPath}/fileup/upload" method="post" enctype="multipart/form-data">
			<input type="file" name="file" id="file"/> 
			<input type="button" value="下达程序" onclick="ajaxFileUpload();"/>
		</div>
	</body>
	</html>

  

 

posted @ 2017-06-05 08:10  半生戎马,共话桑麻、  阅读(432)  评论(0)    收藏  举报
levels of contents