利用開源元件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)
- <?xmlversion="1.0"encoding="UTF-8"?>
- <web-appversion="2.5"xmlns="http://java.sun.com/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
- http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
- <servlet>
- <servlet-name>upload</servlet-name>
- <servlet-class>upload.Upload</servlet-class>
- </servlet>
- <servlet-mapping>
- <servlet-name>upload</servlet-name>
- <url-pattern>/upload</url-pattern>
- </servlet-mapping>
- </web-app>