common-fileupload是jakarta項目組開(kāi)發(fā)的一個(gè)功能很強大的上傳文件組件,可以支持多個(gè)文件同時(shí)上傳,同時(shí)也可以除了將上傳文件保存為文件之外,還可以將上傳的文件數據提取保存至數據庫中,甚至你可以通過(guò)調用其中提供的API,在程序代碼中獲得上傳文件的內容,這樣你就可以處理這些數據了,這個(gè)當然與具體的應用有關(guān)了。
這里只講common-fileupload的簡(jiǎn)單使用入門(mén),一并解決上傳文件中文件名為中文時(shí),上傳之后文件名顯示亂碼的問(wèn)題,這個(gè)解決方法很簡(jiǎn)單,在示例程序代碼中的注釋中有詳細的描述,查看程序就可以明白了。同時(shí)這里的示例代碼中,只提供了一個(gè)文件上傳框的顯示,但是在后臺提供了多個(gè)文件上傳的讀取支持的,只要能夠基本明白這個(gè)上傳方法,做成多個(gè)文件上傳也不成問(wèn)題。
另外還需說(shuō)明的是,對于上傳文件,通常前臺上傳文件至后臺時(shí),后臺是一個(gè)Servlet來(lái)處理請求,而Servlet處理請求中,通常會(huì )有返回頁(yè)面,所以如果要做到界面顯示,而不會(huì )讓用戶(hù)感覺(jué)有因為上傳而產(chǎn)生的刷屏的樣子,應該做一個(gè)類(lèi)似于AJAX的表現,來(lái)進(jìn)行局部刷新,不過(guò)AJAX本身而言,并不支持form的post方式的文件提交,所以不能用AJAX來(lái)進(jìn)行上傳文件的局部刷新。通常比較好的一種做法是在你的網(wǎng)頁(yè)中內嵌一個(gè)iframe,在iframe里面做一個(gè)form,以進(jìn)行文件上傳的提交。具體示例代碼見(jiàn)下。
本次的上傳使用的Common-FileUpload的版本是最新版,即
好了,不說(shuō)廢話(huà)了,下面貼出示例代碼:
WEB頁(yè)面:
文件名:uploadtest.html
<html>
<head>
<title>文件上傳</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<p>
<b>文件上傳</b>
</p>
<br/>
<br/>
<div id="fileSendDiv">
<iframe width="100%" height="35" frameborder="0" id="show" name="show" src="uploadfile.jsp" scrolling="no" style="frameborder:0" align="left"></iframe>
</div>
<br/>
<br/>
<br/>
<br/>
<p>
<b>刷新的是iframe,父頁(yè)面不會(huì )改變</b>
</p>
</body>
</html>
該頁(yè)面注意的是iframe的使用,刷新的會(huì )是iframe,iframe指向了一個(gè)新的文件,文件名叫:uploadfile.jsp,這個(gè)才是真正的上傳文件的內容表現,你可以將這個(gè)文件作為工具類(lèi)型的文件,只要在上傳文件中通過(guò)iframe引用這個(gè)文件即可(uploadtest.html與uploadfile.jsp處于同一個(gè)目錄中)。
上傳顯示文件代碼如下:
文件名:uploadfile.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W
<html>
<head>
<title>上傳文件</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<script language="JavaScript" type="text/javascript">
function upload()
{
var filename = document.tab.uploadfile.value;
if (filename=='')
{
alert("沒(méi)有選擇要上傳的文件,請選擇!");
return;
}
document.tab.action = "FileUpload";//提交上傳為文件時(shí),所指向的servlet配置的Servlet動(dòng)作
document.tab.target="show";//指向iframe的ID,即刷新頁(yè)面返回時(shí)所指的地方。
document.tab.submit();
}
</script>
</head>
<body style="margin:0px;">
<form name="tab" method="post" action="" enctype="multipart/form-data">
<input type="file" id="uploadfile" name="uploadfile" style="border:1px solid black;" >
<input type="button" name="up" value="上傳" style="border:1px solid black;height:20px;" onClick="upload()">
</form>
</body>
</html>
需要明確的是該上傳文件當調用upload之后,其返回所指向的是ID為show表單,查看uploadtest.html中的iframe發(fā)現,指的就是這個(gè)iframe的ID,所以說(shuō)當后臺的Servlet有返回時(shí),刷新的也只是這個(gè)iframe,而不會(huì )影響整個(gè)父頁(yè)面的顯示效果。
下面是后臺Servlet的源代碼:
文件名:UploadFileTest.java
package com.uploadtest;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
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.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
public class UploadFileTest extends HttpServlet {
private static final long serialVersionUID =
private static final String CONTENT_TYPE = "text/html; charset=utf-8";
//Process the HTTP Post request
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String path = request.getContextPath();
//WEB形式的表現地址,示例:http://127.0.0.1:8080/uploadtest/
String basePath = request.getScheme() + "://" + request.getServerName()
+ ":" + request.getServerPort() + path + "/";
//獲得本地地址,示例如:c://tomcat/webapp/
String temp = getServletContext().getRealPath("/") + "upload/temp"; //臨時(shí)目錄
String loadpath = getServletContext().getRealPath("/") + "upload"; //上傳文件存放目錄
response.setContentType(CONTENT_TYPE);
PrintWriter out = response.getWriter();
try {
//Create a factory for disk-based file items
DiskFileItemFactory factory = new DiskFileItemFactory();
//Set factory constraints設置最多只允許在內存中存儲的數據,單位:字節
factory.setSizeThreshold(4096);
//設置一旦文件大小超過(guò)getSizeThreshold()的值時(shí)數據存放在硬盤(pán)的目錄(緩存)
factory.setRepository(new File(temp));
//Create a new file upload handler
ServletFileUpload upload = new ServletFileUpload(factory);
// Set overall request size constraint設置允許用戶(hù)上傳文件大小,單位:字節,這里設為
upload.setSizeMax(5 * 1024 * 1024);
//Parse the request
List /* FileItem */fileItems = upload.parseRequest(request);
//開(kāi)始讀取上傳信息
// 依次處理每個(gè)上傳的文件
Iterator iter = fileItems.iterator();
while (iter.hasNext()) {
FileItem item = (FileItem) iter.next();
//忽略其他不是文件域的所有表單信息
if (!item.isFormField()) {
String name = item.getName();
long size = item.getSize();
if ((name == null || name.equals("")) && size == 0)
continue;
name = name.substring(name.lastIndexOf("\\") + 1);//從全路徑中提取文件名
//處理中文編碼問(wèn)題,前臺是UTF-8,所以這里需要對應上,如果前臺是gb2312的話(huà),這里也應該是gb2312
name = new String(name.getBytes(), "utf-8");
try {
//保存上傳的文件到指定的目錄
//在下文中上傳文件至數據庫時(shí),將對這里改寫(xiě)
File fNew = new File(loadpath, name);
item.write(fNew);
//out.print(name + " " + size + "");
response.sendRedirect(basePath + "uploadfile.jsp");//返回刷新頁(yè)面,即返回iframe
}
catch (Exception e) {
e.printStackTrace();
out.println(e);
}
}
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}
具體的調用說(shuō)明,見(jiàn)源文件中的注釋
最后就剩下web.xml的配置了,下面是示例:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>UploadFile</display-name>
<servlet>
<description></description>
<display-name>FileUpload</display-name>
<servlet-name>FileUpload</servlet-name>
<servlet-class>
com.uploadtest.UploadFileTest
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>FileUpload</servlet-name>
<url-pattern>/FileUpload</url-pattern>
</servlet-mapping>
</web-app>
好了,一個(gè)完整的使用Common-FileUpload的例子就結束了。
最后要提一點(diǎn),就是這個(gè)上傳組件中,在解析上傳文件時(shí),會(huì )讀取上傳文件的內容的,有時(shí)在應用中,比如WEB呼叫中心方面,WEB端上傳的文件會(huì )被遠端的人員接收,但是有時(shí)的情況下,遠端服務(wù)人員并不一定希望接收WEB端發(fā)過(guò)來(lái)的文件,所以即便是遠端服務(wù)人員拒絕了接收文件,但是這個(gè)上傳組件卻是已經(jīng)讀取了文件的內容至緩存中了,也就是說(shuō)多做了一步。并且即便是遠端服務(wù)人員愿意接收文件,它也是有延遲的,過(guò)程是先從WEB中接收文件至緩存中,再從緩存中提取數據傳至遠端的服務(wù)人員。估計可以通過(guò)改變這個(gè)上傳組件的源代碼,來(lái)回避上面所說(shuō)的問(wèn)題,不過(guò)需要對源代碼有一定的研究。
至于用到該上傳組件的一些高級功能(如要做一個(gè)上傳進(jìn)度條的顯示),可以看它提供的User Guide,進(jìn)行自身功能的定義了,本文只做入門(mén)級介紹。
聯(lián)系客服