Java 上傳文件到ftp服務器

         前兩篇文章我們搭建了一個ftp服務器,並對服務器進行了相應的配置,這篇文章我們來說一下我們如何上傳文件。

         先介紹一下項目,本項目採用的是spring mvc +spring +mybatis ,用maven 進行項目管理。看一下項目結構 。

        

        如果單獨做測試的話不用這麼費勁,寫一個簡單的測試類就ok了!而在這個項目中,parent是所有項目的父包,其他的項目都把該項目做爲父項目。common中放入的是一些公用的工具類,pojo對象等,pojo和mapper項目是mybatis逆向生成的項目。而service 是處理業務邏輯的項目,web 是展示層的項目。介紹完了,直接看我們要求的代碼。

        上傳文件需要的工具類。代碼如下所示,這個東西一般不用自己再寫了,網上有很多,直接找一個用就可以了,但是要弄懂它的意思。

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, port);// 連接FTP服務器
			// 如果採用默認端口,可以使用ftp.connect(host)的方式直接連接FTP服務器
			ftp.login(username, password);// 登錄
			reply = ftp.getReplyCode();
			if (!FTPReply.isPositiveCompletion(reply)) {
				ftp.disconnect();
				return result;
			}
			//切換到上傳目錄
			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);
			//上傳文件
			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服務器下載文件 
	 * @param host FTP服務器hostname 
	 * @param port FTP服務器端口 
	 * @param username FTP登錄賬號 
	 * @param password FTP登錄密碼 
	 * @param remotePath FTP服務器上的相對路徑 
	 * @param fileName 要下載的文件名 
	 * @param localPath 下載後保存到本地的路徑 
	 * @return 
	 */  
	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;
	}
}

         我們的pojo項目和mapper項目,不需要寫代碼,在service層要做一些處理,判斷是否上傳成功。會看到如何代碼有很多的獲取值的,因爲我們不能見ftp服務器的一些信息都寫死到代理嗎,我們要把它放入配置文件中,可以是xml文件,或者properties等,這裏採用的是properties文件形式。Service 項目是jar 類型的,最後要打成jar包,放入到web項目中,所以所有的配置文件信息應該都放入web項目中。

          

         我們ftp配置信息在resource.properties文件中,如下所示,在寫這個配置文件的時候千萬要注意所有的值前後不要空格,所有的值前後不要空格,所有的值前後不要空格,重要的事情講三遍,我就是因爲一個空格弄了整整半天。

          

#ftp相關配置
FTP_ADDRESS=192.168.xx.xxx
FTP_PORT=21
FTP_USERNAME=ftpuser
FTP_PASSWORD=123456
FTP_BASEPATH=/home/ftpuser/www/images
#圖片服務器相關配置i
IMAGE_BASE_URL=http://192.168.xx.xxx/www/images

         配置完resource.properties以後,要確保在項目啓動的時候一定要加載這個文件,在配置文件中加上這句話。<!-- 加載配置文件 -->

         <context:property-placeholderlocation="classpath:resource/*.properties" /> 這樣就可以保證配置文件會被加載了。

         然後我們在service中寫自己的業務邏輯,

        

@Service
public class PictureServiceImpl implements PictureService {

	//獲取ip地址
	@Value("${FTP_ADDRESS}")
	private String FTP_ADDRESS;
	//端口號
	@Value("${FTP_PORT}")
	private String FTP_PORT;
    //用戶名
	@Value("${FTP_USERNAME}")
	private String FTP_USERNAME;
	//密碼
	@Value("${FTP_PASSWORD}")
	private String FTP_PASSWORD;
	//基本路徑
	@Value("${FTP_BASEPATH}")
	private String FTP_BASEPATH;
	//下載地址地基礎url
	@Value("${IMAGE_BASE_URL}")
	private String IMAGE_BASE_URL;

	@Override
	public Map uploadPicture(MultipartFile uploadFile) {
		Map resultmMap = new HashMap<>();

		try {
			// 生成一個文件名
			// 獲取舊的名字
			String oldName = uploadFile.getOriginalFilename();
			String newName = IDUtils.genImageName();
			//新名字
			newName = newName + oldName.substring(oldName.lastIndexOf("."));
			//上傳的路徑
			String imagePath = new DateTime().toString("/yyyy/mm/dd");
			//端口號
			int port = Integer.parseInt(FTP_PORT);
			System.out.println(FTP_BASEPATH);
			//調用方法,上傳文件
			boolean result = FtpUtil.uploadFile(FTP_ADDRESS, port,
					FTP_USERNAME, FTP_PASSWORD, FTP_BASEPATH, imagePath,
					newName, uploadFile.getInputStream());
			//判斷是否上傳成功
			if (!result) {
				resultmMap.put("error", 1);
				resultmMap.put("message", "上傳失敗");
				return resultmMap;
			}
			resultmMap.put("error", 0);
			resultmMap.put("url", IMAGE_BASE_URL + imagePath + newName);
			return resultmMap;

		} catch (IOException e) {
			resultmMap.put("error", 1);
			resultmMap.put("message", "上傳發生異常");
			return resultmMap;
		}
	}
}

         Controler中服務請求的轉發工作。代碼如下。

@Controller
public class PictureController {
	
	@Autowired
	private PictureService pictureService;
	
	@RequestMapping("/pic/upload")
	@ResponseBody
	public Map pictureUpload(MultipartFile uploadFile){
		Map result = pictureService.uploadPicture(uploadFile);
		return result;
	}
}

         在jsp 頁面中我們用

<span style="font-size:18px;">    <a href="javascript:void(0)" class="easyui-linkbuttonpicFileUpload">上傳圖片</a>
   <inputtype="hidden" name="image"/></span>

         而調用到js代碼如下所示

        

 // 初始化圖片上傳組件
    initPicUpload : function(data){
    	$(".picFileUpload").each(function(i,e){
    		var _ele = $(e);
    		_ele.siblings("div.pics").remove();
    		_ele.after('\
    			<div class="pics">\
        			<ul></ul>\
        		</div>');
    		// 回顯圖片
        	if(data && data.pics){
        		var imgs = data.pics.split(",");
        		for(var i in imgs){
        			if($.trim(imgs[i]).length > 0){
        				_ele.siblings(".pics").find("ul").append("<li><a href='"+imgs[i]+"' target='_blank'><img src='"+imgs[i]+"' width='80' height='50' /></a></li>");
        			}
        		}
        	}
        	//給“上傳圖片按鈕”綁定click事件
        	$(e).click(function(){
        		var form = $(this).parentsUntil("form").parent("form");
        		//打開圖片上傳窗口
        		KindEditor.editor(TT.kingEditorParams).loadPlugin('multiimage',function(){
        			var editor = this;
        			editor.plugin.multiImageDialog({
						clickFn : function(urlList) {
							var imgArray = [];
							KindEditor.each(urlList, function(i, data) {
								imgArray.push(data.url);
								form.find(".pics ul").append("<li><a href='"+data.url+"' target='_blank'><img src='"+data.url+"' width='80' height='50' /></a></li>");
							});
							form.find("[name=image]").val(imgArray.join(","));
							editor.hideDialog();
						}
					});
        		});
        	});
    	});
    },

         這些代碼都寫完以後,我們測試會發現依然有問題,Expected MultipartHttpServletRequest: is a MultipartResolverconfigured 這個錯誤是因爲我們沒有配置解析文件的jar。所以我們還要在springmvc的配置文件中加上如下配置。這樣我們應該就沒問題了!

<span style="font-size:18px;"><!-- 上傳文件攔截,設置最大上傳文件大小10M=10*1024*1024(B)=10485760 bytes -->
   <bean id="multipartResolver"
   class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
     <property name="maxUploadSize"value="10485760" />
   </bean></span>

         這樣我們就可以了,如果有需要源碼的情單獨聯繫我。不方便放入資源中!


   

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章