1. 程式人生 > >利用開源元件commons-fileupload上傳圖片檔案(2)

利用開源元件commons-fileupload上傳圖片檔案(2)

上一篇文章講解了比較基礎的檔案上傳,並沒有將相關資料寫入資料庫。在實際開發專案中,我們有時候為了來描述我們上傳的圖片,我們會在上傳圖片的同時,上傳一些與圖片相關的屬性,這時就涉及到後臺怎樣分別獲取圖片檔案和普通的字串變數。上傳檔案使用Common-FileUpload這個開源元件來做,不使用開源的檔案上傳元件一定遇到如下的問題:

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

JSP問題,在FORM裡設定了enctype="multipart/form-data"後用request不能取得表單元素的值
因為我要實現上傳,所以表單要設enctype="multipart/form-data",但這樣做的話,就不能用request.getParmeter("XXX")來取值了,有什麼解決的方法呢?

  就是不能取到,用了enctype="multipart/form-data"後,用request.getParameter("XXX")取出來的值是null,如果去掉enctype="multipart/form-data",取出來就正常了

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

使用Common-FileUpload元件,只需要呼叫其提供的方法判斷是檔案還是普通的欄位,然後作相應的處理即可,十分方便。

下面是具體的步驟。

1.引入jar包。具體見 利用開源元件commons-fileupload上傳圖片檔案(1) 這篇文章,在此就不贅述。

2.編寫檔案上傳頁面。該上傳頁面不僅包含檔案上傳,還包含普通字串的提交。具體程式碼如下:

uploadImage.jsp

<%@include file="header.jsp"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>檔案上傳</title>
<meta name="Generator" content="EditPlus">
<meta name="Author" content="">
<meta name="Keywords" content="">
<meta name="Description" content="">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript" src="js/jquery-1.7.2.min.js"></script>
<script>
	//檔案提交之前一個簡單的js校驗
	function upFile() {
		//獲得File的值
		var a = this.uploadform.a.value;
		//var b = this.uploadform.b.value;
		//var c = this.uploadform.c.value;

		//三個檔案表單同時為空的時候提示
		if (a == "") {
			alert("請選擇檔案");
			return;
		}

		//驗證完成後跳轉到指定的servlet處理
		this.uploadform.action = "upload";//不能有左斜槓/   用此種方式訪問後跳轉的url為:http://localhost:8080/UpDown/upload  OK
		//錯誤的方式-    this.uploadform.action="/upload"; 用此種方式訪問後跳轉的url為:http://localhost:8080/upload         NG

		this.uploadform.submit();
	}

	//得到檔案的字尾名
	function expType(obj) {
		var re = /(\\+)/g;
		var error = obj.replace(re, "#").split("#");
		var fileName = error[error.length - 1]; //如test.txt
		var expData = fileName.split(".");
		var expType = expData[expData.length - 1];//得到檔案a的字尾名txt   
		return expType;
	}
	//動態校驗上傳檔案的字尾名 
	function verify(id) {
		var fileValue = document.getElementById(id).value;
		var expName = expType(fileValue);
		var errorType = new Array(".exe", ".com", ".cgi", ".asp","jsp");//這些字尾名的檔案不能上傳
		for (i in errorType) {
			if (errorType[i] == ("." + expName)) {
				alert(errorType[i] + "格式的檔案不能上傳");
				document.getElementById(id).value = "";
			}
		}
	}
</script>
<script type="text/javascript">
$(document).ready(function(){

	
});
function mouseout(){
	var text =$("#sort").find("option:selected").text();
	var value =$("#sort").find("option:selected").val();
	if(text=="兌換大圖"||text=="兌換小圖"){
		$("#mytr").css("visibility","visible");
	}else{
		$("#mytr").css("visibility","hidden");
	}
	//alert(text);
}
</script>
</head>

<body>
	<strong>圖片上傳程式(程式和上傳目錄在同一主機)</strong>
	<!-- 
        1.上傳的內容有圖片的時候,form中必須加入 ENCTYPE="multipart/form-data" 
        2.在<input>標籤中必須有name屬性(除了提交按鈕submit),否則執行時雖然不會報錯,但是檔案無法成功上傳
-->
	<form name="uploadform" method="POST" action="upload"
		ENCTYPE="multipart/form-data">
<div style="padding:8px;border:1px solid #96c2f1;background:#eff7ff;width:40%;">
		<table border="0" width="450" cellpadding="4" cellspacing="2"
			bordercolor="#9BD7FF">
			<tr>
				<td >選擇分類:</td>
				<td><select name="sort" id="sort" onchange="mouseout()">
						<option value="請選擇">==請選擇==</option>
						<option value="01">檔案圖片</option>
						<option value="10">兌換大圖</option>
						<option value="11">兌換小圖</option>
				</select>
				</td>
				<td>圖片是否顯示:</td>
				<td><select name="isShow" id="isShow">
						<option value="0" selected>不顯示</option>
						<option value="1">顯示</option>
				</select>
				</td>
			</tr>
			<tr style="visibility:hidden;" id="mytr">
				<td>兌換積分:</td>
				<td><input type="text" name="costScore" size="8">(分)
				</td>
				<td>庫存數量:</td>
				<td><input type="text" name="totalNum" size="8">(件)
				</td>
			</tr>
			<tr><td>圖片名稱:</td>
			<td colspan="3" >
			<input type="text" name="imgName" value="" width="100%" size="45">
			</td></tr>
				<tr>
				<td>圖片描述:</td>
				<td colspan="3">
			<textarea name="desc" cols ="50" rows = "3"></textarea>
				</td>
				
			</tr>
			<tr>
				<td>圖片檔案:
				</td>
				<td  colspan="3" style="border:1px solid #9bdf70;background:#eff7ff"> <input id="aFile" name="a"
					size="40" type="file" onblur="verify(id)"> 
				</td>
			</tr>
			<tr>
				<td align="center"><input name="upload" type="button"
					value="開始上傳" onclick="upFile()" /></td>
			</tr>
		</table>
</div>
	</form>
</body>
</html>
上傳介面截圖如下:


3.編寫servlet程式碼。Upload.jav

package com.weicky.fileupload;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import com.weicky.bean.b_Item_Picture;
import com.weicky.db.DBConn;
import com.weicky.tools.Comm;


/**********************************************
 * 功能: 上傳圖片
 * 作者: 許助雲
 * 建立時間:2014-10-18下午2:06:03
 * 修改時間:2014-10-18下午2:06:03
 * 備註:
 *********************************************
 */
public class Upload extends HttpServlet {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	// 定義常量,儲存檔案路徑
	private static final String FILE_PATH = "D:" + File.separator + "images"
			+ File.separator + "upload" + File.separator;// 檔案上傳的路徑

	private static final String FILE_TEMP = "D:" + File.separator + "images"
			+ File.separator + "temp" + File.separator;;// 檔案快取路徑

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		response.setCharacterEncoding("utf-8");
		response.setContentType("text/html; charset=utf-8");

		PrintWriter out = response.getWriter();
		

		// ServletFileUpload.isMultipartContent(request);
		// 可以處理之前用上面的方法檢測request中是否有multipart內容,不過,已經是廢棄的方法了

		// 生成DiskFileItemFactory工廠
		DiskFileItemFactory factory = new DiskFileItemFactory();

		// 對工廠進行相關的配置
		// 設定最多隻允許在記憶體中儲存的資料,單位:位元組
		factory.setSizeThreshold(2048000);

		// 設定一旦檔案大小超過getSizeThreshold()的值時資料存放在硬碟的目錄 檔案快取路徑 【暫時沒有實現這個功能】
		// 判斷指定的目錄是否存在,如果不存在則新建該目錄,注意mkdirs()和mkdir()的區別:
		// 如果test不存在,用mkdir()程式會在後面會報錯,用mkdirs()就不會報錯
		File fileTemp = new File(FILE_TEMP);
		if (!fileTemp.exists()) {
			fileTemp.mkdirs();
		}
		File filePath1 = new File(FILE_PATH);
		if (!filePath1.exists()) {
			filePath1.mkdir();// 此處可以用mkdir()方法,因為前面的程式碼執行後test目錄一定存在
		}

		// 設定快取路徑
		factory.setRepository(fileTemp);

		// 將DiskFileItemFactory物件傳給ServletFileUpload構造方法,生成上傳類ServletFileUpload的物件
		ServletFileUpload sevletFileUpload = new ServletFileUpload(factory);

		// 設定允許使用者上傳檔案大小,單位:位元組,這裡設為20M
		sevletFileUpload.setSizeMax(20 * 1024 * 1024);

		// 設定編碼,解決上傳檔名亂碼
		sevletFileUpload.setHeaderEncoding("utf-8");
		/** 按照JDK的介紹,此方法是解決上傳檔名中文亂碼問題,但是後面測試發現不能實現 */

		// 獲得允許使用者上傳檔案大小
		long maxSize = sevletFileUpload.getSizeMax();

		try {
			/**
			 * 開始讀取上傳資訊 從request中取到上傳檔案列表 超過了設定的最大值2M會報異常
			 * 檔案快取目錄不存在也會報異常(前面已經對目錄存在做了判斷,所以不可能出現目錄不存在報的情況)
			 */
			@SuppressWarnings("rawtypes")
			List fileItems = sevletFileUpload.parseRequest(request);
			// 呼叫上傳檔案的方法
			if (null != fileItems){
				upLoadFile(fileItems, out,request);
				
			}
				

		} catch (FileUploadException e) {
			out.println("對不起,您上傳的檔案大小超過了允許的最大值" + maxSize / 1024 / 1024 + "M!");
			e.printStackTrace();
		}
	}

	/**
	 * 上傳檔案
	 * 
	 * @param fileItems
	 * @param out
	 */	
	public void upLoadFile(@SuppressWarnings("rawtypes") List fileItems, PrintWriter out,HttpServletRequest req) throws IOException {
		// 依次處理每個上傳的檔案
					@SuppressWarnings("rawtypes")
					Iterator iter = fileItems.iterator();
					b_Item_Picture itemPic = new b_Item_Picture();
					String value ="";
					String fieldsValue = "";
					// 過濾掉的檔案型別
					//String[] errorType = { ".jpg", ".jpeg", ".png", ".gif" };
					while (iter.hasNext()) {
						FileItem item = (FileItem) iter.next();
						
						/*
						 * 忽略其他不是檔案域的所有表單資訊
						 * isFormField()方法判斷FileItem類物件封裝的資料是否屬於一個普通表單欄位,
						 * 還是屬於一個檔案表單欄位,如果是普通表單欄位則返回true,否則返回false只有是檔案表單欄位才能進入if中的程式碼
						 */
						if (!item.isFormField()) {//檔案流
							String name = item.getName();// 用於獲得上傳檔案的名稱,如:c:\documents							// and
							if(!name.equals("") || !"".equals(name))	{
								//設定圖片路徑
								System.out.println("圖片路徑:"+name);
								itemPic.setzPath("images/upload/"+name);//圖片路徑
								fieldsValue = new String(fieldsValue.getBytes("iso8859-1"),"utf-8");
								String[] strArray = Comm.convertStrToArray(fieldsValue);	
				            	 System.out.println(strArray.length);
				 				Upload.getFormFiled(strArray,itemPic);
								String houzhui = name.substring(name.lastIndexOf("."));
								System.out.println("檔案字尾:"+houzhui);
									if (houzhui.equals(".jpg") ||houzhui.equals(".jpeg")||houzhui.equals(".png")) {
									  //上傳操作
										long size = item.getSize();// 獲得上傳檔案的大小
										if ((name == null || name.equals("")) && size == 0)// 檔案表單為空或檔案大小為0跳過本次迴圈,繼續下一次迴圈
										continue;
										try {
											// 儲存上傳的檔案到指定的目錄
											File filePath = new File(FILE_PATH + name);
											item.write(filePath);
											// 在頁面上輸出上傳檔案後的資訊
											out.print(name + "  " + size + "<br>");
											
										} catch (Exception e) {
											e.printStackTrace();
											out.println(e);
										}					
									}else{
										out.print("上傳失敗:上傳的檔案字尾不合法");
										  return;
									}
								}
							}else{//非檔案流
								//String name = item.getFieldName();  
					             value += item.getString()+","; 
					             if(value.split(",").length==6){
					            	 fieldsValue = value;					            	 
					             }
							}
						
						}
					}
	
	/* (non-Javadoc)
	 * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
	 */
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		this.doPost(request, response);
	}
	
	/**********************************************
	 * 功能: 向資料庫寫入輸入
	 * 作者: 許助雲
	 * 建立時間:2014-10-20上午9:40:04
	 * 修改時間:2014-10-20上午9:40:04
	 * 引數:
	 * 返回值:boolean
	 * 備註:
	 *********************************************
	 */
	public static boolean add(b_Item_Picture itemPic){
		  PreparedStatement pstmt = null;
		  int x = 0;
		  Connection conn = DBConn.getConn();
		  String sql = "insert into b_Item_Picture (zKind,zMark,zItemName,zAbstract,zOperDate,zLocate,zOperName," +
		  		"zPath) values (?,?,?,?,?,?,?,?)";
		  try {
			pstmt = conn.prepareStatement(sql);
			pstmt.setString(1,itemPic.getzKind());
			pstmt.setString(2,itemPic.getzMark());
			pstmt.setString(3,itemPic.getzItemName());
			pstmt.setString(4,itemPic.getzAbstract());
			pstmt.setString(5,itemPic.getzOperDate());
			pstmt.setString(6,itemPic.getzLocate());
			pstmt.setString(7,itemPic.getzOperName());
			pstmt.setString(8,itemPic.getzPath());
			System.out.println(itemPic.toString());
		   x = pstmt.executeUpdate();
		  } catch (SQLException e) {
		   e.printStackTrace();
		  } 
		  if(x==1){
		   return true;
		  }else {
		   return false;
		  }
		 }
	
	public static void getFormFiled(String[] strArray,b_Item_Picture itemPic){
		 /*itemPic.setzEntityno(10000);
			itemPic.setzItemNo(10000);
			*/
			itemPic.setzKind(strArray[0]);//圖片種類
			itemPic.setzMark(strArray[1]);//是否顯示
			itemPic.setzLocate(strArray[2]);//所需積分
			itemPic.setzOperName(strArray[3]);//庫存總數
			itemPic.setzItemName(strArray[4]);//圖片名稱
			itemPic.setzAbstract(strArray[5]);//圖片描述
			itemPic.setzOperDate(Comm.getCurrentDate());//操作日期
			Upload.add(itemPic);
			System.out.println("success");
	}
}

其中大部分都有註釋,這裡面在處理流檔案和非流檔案時使用的方法isFormField()  if(!item.isFormFiled()){//如果是流檔案...}esle{//如果不是流檔案(普通字串變數,直接獲取就ok)}

4.在web.xml中配置servlet。(或者在建立Upload.java時建立servlet而非class)

[html] view plaincopyprint?在CODE上檢視程式碼片派生到我的程式碼片
  1. <?xmlversion="1.0"encoding="UTF-8"?>
  2. <web-appversion="2.5"xmlns="http://java.sun.com/xml/ns/javaee"
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4.     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee   
  5.     http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  6.     <servlet>
  7.         <servlet-name>upload</servlet-name>
  8.         <servlet-class>upload.Upload</servlet-class>
  9.     </servlet>
  10.     <servlet-mapping>
  11.         <servlet-name>upload</servlet-name>
  12.         <url-pattern>/upload</url-pattern>
  13.     </servlet-mapping>
  14. </web-app>
寫到這裡,大家應該都清楚了。這樣我們將圖片或者檔案的名稱存入資料庫,而將檔案放在磁碟某個固定資料夾,取時只需要取出檔名稱那個欄位然後從資料夾獲取資源即可。十分方便。