阅读本文需要具备JSP、Servlet基础知识
swfupload主页:http://code.google.com/p/swfupload/
swfupload文档:http://www.leeon.me/upload/other/swfupload.html
从主页下载例程,两个文件是必需的:swfupload.js和swfupload.swf。界面和回调函数我都是自己写的。
jsp中代码片段:
说明:获取基址,提高程序健壮性
<%
StringBuffer base = new StringBuffer("http://");
base.append(request.getHeader("Host"));
base.append(request.getContextPath()+"/");
%>
编写界面:
界面中一般放置三个按钮:浏览文件、开始上传、取消上传。
开始上传和取消上传这两个按钮如何实现随便。如果图简单用input就行。需要说明的是浏览文件这个按钮是由swfupload生成的,你只需要标注好其位置即可,比如:
<span id=“open”></span>
id名称随你怎么起,只要和后面代码里button_placeholder_id保持一致就行。
swfupload初始化:
里面一些字符串参数是我项目中用的,你项目中会有不同形式
注意:创建代码应在页面加载完毕后执行,例如window.onload 我项目中因其它需求采用的是window.setTimeout廷时执行方式
swfu = new SWFUpload({
upload_url: '<%=base.toString()%>'+"/fileupload", //servlet 后面介绍其详细代码
post_params: {"id" : id},//向servlet传送参数
// File Upload Settings
file_size_limit : "1024 MB",
file_types : "*.gif;*.png;*.jpg",
file_types_description : "图片文件",
file_upload_limit : "20",
use_query_string : true,//要传递参数,必须配置
file_queue_error_handler : fileQueueError,
file_dialog_complete_handler : fileDialogComplete,//选择好文件后提交
file_queued_handler : fileQueued,
upload_progress_handler : uploadProgress,
upload_error_handler : uploadError,
upload_success_handler : uploadSuccess,
upload_complete_handler : uploadComplete,
// Button Settings
//按钮图片,注意:按钮高度是22px,建议采用88px高,从上至下分别是正常状态、mouseover状态...懂CSS的不解释,不懂的可以去下载的例程中找图片用。
button_image_url : '<%=base.toString()%>'+"images/upbt.png",
button_placeholder_id : btid,
button_width: 82,//宽度可自定义
button_height: 22,//高度不用改了,这样可以直接使用例程中图片
button_text : '选择文件',
button_text_style : '.button { font-family: Helvetica, Arial, sans-serif; font-size: 12pt; } .buttonSmall { font-size: 10pt; }',
button_text_top_padding: 0,
button_text_left_padding: 8,
button_window_mode: SWFUpload.WINDOW_MODE.TRANSPARENT,
button_cursor: SWFUpload.CURSOR.HAND,
// Flash Settings
flash_url : '<%=base.toString()%>'+"js/swfupload.swf",
custom_settings : {
upload_target : "divFileProgressContainer"
},
// Debug Settings
debug: false //是否显示调试窗口
});
回调函数:
swfupload支持多文件上传,它可以同时选择多个文件,这些文件将被添加至swfupload的队列中。你需要做的是控制何时开始上传和处理swfupload的回调函数,当然还可以终止上传。
回调函数中主要是根据回调函数传递的信息处理你的界面,需要调用的swfupload方法主要是swfu.cancelUpload(fileid,false)和swfu.startUpload()
先介绍下回调函数参数中所用file对象:
/**
* file
* id : string, // SWFUpload控制的文件的id,通过指定该id可启动此文件的上传、退出上传等
* index : number, // 文件在选定文件队列(包括出错、退出、排队的文件)中的索引
* name : string, // 文件名,不包括文件的路径。
* size : number, // 文件字节数
* type : string, // 客户端操作系统设置的文件类型
* creationdate : Date, // 文件的创建时间
* modificationdate : Date, // 文件的最后修改时间
* filestatus : number // 文件的当前状态,对应的状态代码可查看SWFUpload.FILE_STATUS }
*/
fileQueued(file)
说明:
当文件选择对话框关闭消失时,如果选择的文件成功加入上传队列,
那么针对每个成功加入的文件都会触发一次该事件(N个文件成功加入队列,就触发N次此事件)。
fileQueueError(file, errorCode, message)
说明:在高传输队例添其它 message
fileDialogComplete(numFilesSelected, numFilesQueued)
说明:
文件选择对话框关闭,numFilesQueued 表示有几个文件被添加到了上传队列。
function uploadProgress(file, bytesLoaded)
说明:
上传进度,函数里可以控制你自己的进度条
function uploadSuccess(file, serverData)
说明:
serverData是服务器返回数据,你在servlet中返回的数据在这里接收
function uploadComplete(file) {
try {
/* I want the next upload to continue automatically so I'll call startUpload here */
if (this.getStats().files_queued > 0) {
this.startUpload();
} else {
//所有文件上传完毕
}
} catch (ex) {
this.debug(ex);
}
}
function uploadError(file, errorCode, message) {
try {
switch (errorCode) {
case SWFUpload.UPLOAD_ERROR.FILE_CANCELLED:
//上传被取消
break;
case SWFUpload.UPLOAD_ERROR.UPLOAD_STOPPED:
//上传中止
break;
case SWFUpload.UPLOAD_ERROR.UPLOAD_LIMIT_EXCEEDED:
//文件超出上限
break;
default:
break;
}
} catch (ex) {
}
}
回调函数的功能简要介绍到这里,详情可参照文档说明
Servlet代码:
需要引用commons-fileupload包和commons-io-1.3.2包
import java.io.File; import java.io.IOException; 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; public class FileUploadServlet extends HttpServlet { private static final long serialVersionUID = 482427761L; public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { DiskFileItemFactory factory = new DiskFileItemFactory(); factory.setSizeThreshold(10240000); String base = "d:/upload"; File file = new File(base); if (!(file.exists())) file.mkdirs(); factory.setRepository(file); ServletFileUpload upload = new ServletFileUpload(factory); upload.setFileSizeMax(1412465408L); upload.setSizeMax(1412465408L); upload.setHeaderEncoding("UTF-8"); try { List items = upload.parseRequest(request); FileItem item = null; String fileName = null; for (int i = 0; i < items.size(); ++i) { item = (FileItem)items.get(i); fileName = base + File.separator + item.getName(); if ((!(item.isFormField())) && (item.getName().length() > 0)) item.write(new File(fileName)); } } catch (FileUploadException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } }
注意:
我当初看到for (int i = 0; i < items.size(); ++i)这个代码,我想是不是所有队例中文件全在这一个请求中处理了,事实证明每个文件执行这个servlet一次。
关于在firefox和chrome中使用的问题:
在这两种浏览器中flash会创建不同的session,但事实上我发现这其实并不影响上传,之所以网上很多关于这方面贴子,是因为现在java web中经常存在url过滤。昨天在回调函数中接收serverData,意外发现居然是我loading.jsp的代码,开始直接蒙了,后来明白是flash的session过不了我的url过滤,而url过滤中对失败的验证会转至loding.jsp,所以造成前面现像。由此我觉得对于文件上传没必要使用url过滤了,把请求地址改出url过滤范围外。