SWFUpload初体验 For Struts1.x

时间:2021-11-16 06:01:22

SWFUpload是一个客户端文件上传工具,最初由Vinterwebb.se开发,它通过整合FlashJavaScript技术为WEB开发者提供了一个具有丰富功能继而超越传统<input type="file" />标签的文件上传模式。

当前版本v2.2.0.1

官网示例:demo.swfupload.org

官方文档:http://demo.swfupload.org/Documentation/

下载地址:https://code.google.com/p/swfupload/downloads/list

示例环境:

Jboss323 + Struts 1

主要特点

  • 可以同时选择多个文件
  • 类似AJAX的无刷新上传
  • 可以显示上传进度
  • 良好的浏览器兼容性
  • 兼容其他JavaScript库 (例如:jQuery, Prototype等)
  • 支持Flash 8和Flash 9及更高版本

原理简介:

传统File标签多文件上传

SWFUpload初体验 For Struts1.x

SWFUpload多文件上传

SWFUpload初体验 For Struts1.x

开始配置

准备工作:

从官网下载的压缩包中,拿到以下文件(附件中有整理好的文件)

SWFUpload v2.2.0.1 Core\swfupload.js

SWFUpload v2.2.0.1 Core\Flash\swfupload.swf

SWFUpload v2.2.0.1 Samples\demos\simpledemo\js\fileprogress.js

SWFUpload v2.2.0.1 Samples\demos\simpledemo\js\handlers.js

SWFUpload v2.2.0.1 Samples\demos\simpledemo\js\swfupload.queue.js

放在指定文件夹中

deploy\media\swfupload

SWFUpload初体验 For Struts1.x

swfupload.swf、swfupload.js是核心文件

handlers.js是事件处理

fileprogress.js是文件队列处理

mimetype.properties是mime类型码表

从页面初始化到用户选择文件最后上传结束是这样的一个过程:

a页面载入(初始化选择控件)—b用户选择多文件—c形成文件队列—d触发上传(队列中的文件依次上传)—e后台处理—f向前台返回结果

其中d-e-f将根据文件数量重复执行,从a-f过程中所有的动作都由事件来驱动,可以自定义捕获每个事件,所以对于程序员来说非常适合订制自己的上传界面。

SWFUpload官方对PHP支持比较好,JSP需要修改和移植,而为了适配Struts 1.x更需要解决如下问题:

  1、对表单验证失败的不进行上传,避免服务器资源浪费。

解决办法:用户批量选择完文件后,先存入队列,点击页面的提交按钮,先验证表单各项都正确无误,然后上传文件,最后进行提交。

  2、SWFUpload上传的文件使用file.getContentType()取得的MIME类型总是多媒体。

解决办法:使用MimetypesFileTypeMap用后缀名从资源文件中获取MIME类型。

ManageAffixService.createAttachmentUseSWF(String aWorkID, String aSource)

  3、SWFUpload使用的编码格式是UTF-8,中文名称在GBK下会成乱码。

解决办法:把上传的文件名作为参数,后台用URLDecoder转码获取正确的文件名。

JS控制

/**
* handler.js
*/ function uploadStart(file) {
try {
/*
设置参数
aFileName 文件名称,字符集转码(防止中文乱码)
flag 标识,上传
*/
var post_params = {"aFileName":encodeURIComponent(file.name),"flag_do":"upload"};
this.setPostParams(post_params); var progress = new FileProgress(file, this.customSettings.progressTarget);
progress.setStatus("Uploading...");
progress.toggleCancel(true, this);
}
catch (ex) {}
return true;
} function fileQueueError(file, errorCode, message) {
try { if (errorCode === SWFUpload.QUEUE_ERROR.QUEUE_LIMIT_EXCEEDED) {
alert("您选择的文件超过文件数量限制。\n" + (message === 0 ? "您已达到上传限制。" : (message > 1 ? "您可以再添加 " + message + " 个文件。" : "您不能再添加文件。")));
return;
}
var errInfo = "添加失败\n原因:";
/* comment by stephen
var progress = new FileProgress(file, this.customSettings.progressTarget);
progress.setError();
progress.toggleCancel(false);
*/
switch (errorCode) {
case SWFUpload.QUEUE_ERROR.FILE_EXCEEDS_SIZE_LIMIT:
//progress.setStatus("File is too big.");
errInfo = errInfo + "该文件超过" + this.settings.file_size_limit + "的大小限制。";
this.debug("Error Code: File too big, File name: " + file.name + ", File size: " + file.size + ", Message: " + message);
break;
case SWFUpload.QUEUE_ERROR.ZERO_BYTE_FILE:
//progress.setStatus("Cannot upload Zero Byte files.");
errInfo = errInfo + "0字节文件";
this.debug("Error Code: Zero byte file, File name: " + file.name + ", File size: " + file.size + ", Message: " + message);
break;
case SWFUpload.QUEUE_ERROR.INVALID_FILETYPE:
//progress.setStatus("Invalid File Type.");
errInfo = errInfo + "文件类型错误,系统允许的文件类型为:" + this.settings.file_types;
this.debug("Error Code: Invalid File Type, File name: " + file.name + ", File size: " + file.size + ", Message: " + message);
break;
default:
if (file !== null) {
//progress.setStatus("Unhandled Error");
errInfo = errInfo + "系统未知错误";
}
this.debug("Error Code: " + errorCode + ", File name: " + file.name + ", File size: " + file.size + ", Message: " + message);
break;
}
alert(errInfo + "\n文件:" + file.name + "(" + getNiceFileSize(file.size) +")");
} catch (ex) {
this.debug(ex);
}
} function uploadSuccess(file, serverData) {
var isSuccess = (serverData.indexOf("successed")==0?true:false);
try {
if(isSuccess){
var tr = document.getElementById(file.id);
tr.style.color="green";
var affixID = serverData.substring(serverData.indexOf("affixListString=")+"affixListString=".length);
//每成功上传一个文件,将附件ID返回至页面,保存在Hidden中,多个以,拼接
document.getElementsByName("affixListString")[0].value = affixID + "," + document.getElementsByName("affixListString")[0].value;
}else{
var tr = document.getElementById(file.id);
tr.style.color="red";
}
} catch (ex) {
this.debug(ex);
}
} function uploadComplete(file) {
//上传完成后,判断队列中文件数是否为零
if (this.getStats().files_queued === 0) {
//如果为零,说明文件已经全部上传,此时提交表单
document.forms[0].submit();
}
}
/*
* fileprogress.js
*/ function FileProgress(file,fileListID,swfUploadInstance) {
if(!document.getElementById(file.id)){
/* 选择文件后新增一行,
* 内容包括:文件图标 + 文件名称 + 文件大小 + 删除按钮
*/
var tb = document.getElementById(fileListID);
var tr = tb.insertRow();
tr.setAttribute("id",file.id);
var td = tr.insertCell();
var fileName = file.name;
var fileSize = "0B";
if(file.size){
fileSize=getNiceFileSize(file.size);
}
var fileICON = "<img src='/media/js/swfupload/attachment.png' border='0'/>";
var fileDelButton = "<span id="+file.id+"_del><a><img src='/media/default/images/del.gif' alt='删除' border='0'/></a></span>";
td.innerHTML= fileICON + fileName + "<font color='gray'>(" + fileSize + ")</font>" + fileDelButton;
var delObject = document.getElementById(file.id+"_del");
delObject.onclick = function () {
swfUploadInstance.cancelUpload(file.id);
var tb = document.getElementById(fileListID);
var tr = document.getElementById(file.id);
tb.deleteRow(tr.rowIndex); };
}
}

JSP页面

  • 引入JS文件
  • 定义初始化参数
  • 声明、创建SWF对象
  • 修改提交方式
<%-- 引入JS文件 --%>
<script type="text/javascript" src="/media/js/swfupload/swfupload.js"></script>
<script type="text/javascript" src="/media/js/swfupload/swfupload.queue.js"></script>
<script type="text/javascript" src="/media/js/swfupload/fileprogress.js"></script>
<script type="text/javascript" src="/media/js/swfupload/handlers.js" charset="GBK"></script>
<script type="text/javascript" src="/media/js/swfupload/swfupload.cookies.js"></script>
<script type="text/javascript" src="/media/js/swfupload/swfupload.swfobject.js"></script> <%-- 定义参数 --%>
<bean:define id="courseLecturesForm" type="gds.jwext.lecture.prez.CourseLecturesForm" name="courseLecturesForm" scope="request" toScope="page"/>
<%
//单个文件允许的max大小
double perMaxSize = Double.parseDouble(courseLecturesForm.getTheFileSize()+"");
//perMaxSize数据对应的单位
String sizeUnit = "KB";
//允许上传的文件类型
String ext = "*.*";
//文件上传提交的目标页面
StringBuffer uploadUrl = new StringBuffer("http://");
uploadUrl.append(request.getHeader("Host"));
uploadUrl.append(request.getContextPath());
uploadUrl.append("/jwext/modifyLectureAction.do");
%> <%-- 定义SWFupload对象 --%>
<script type="text/javascript">
<!--
var swfu;
var swfStats;
var fileNumbers = <%=((List)courseLecture.getAffixAccessoryList()).size() %>;
SWFUpload.onload = function () {
var settings = {
flash_url : "/media/js/swfupload/swfupload.swf",
upload_url: "<%=uploadUrl.toString()%>",
file_size_limit : "<%=perMaxSize%> <%=sizeUnit%>",
file_types : "<%=ext%>",
file_types_description : "<%=ext%>",
file_upload_limit : 5,
file_queue_limit : 5,
file_post_name: "uploadFileData",
custom_settings : {
myFileListTarget : "idFileList"
},
debug: false,
auto_upload: false, // button_text: '<span class="theFont">Hello</span>',
// button_text_style: ".theFont { font-size: 16; }",
// button_text_left_padding: 12,
// button_text_top_padding: 3,
button_image_url: "/media/js/swfupload/SmallSpyGlassWithTransperancy_67x18.png",
button_width: "67",
button_height: "18",
button_align: "absmiddle",
button_placeholder_id: "spanButtonPlaceholder",
button_cursor : SWFUpload.CURSOR.HAND,
button_window_mode : SWFUpload.WINDOW_MODE.WINDOW,
button_action : SWFUpload.BUTTON_ACTION.SELECT_FILES, // The event handler functions are defined in handlers.js
swfupload_loaded_handler : swfUploadLoaded,
file_queued_handler : fileQueued,
file_queue_error_handler : fileQueueError,
file_dialog_complete_handler : fileDialogComplete,
upload_start_handler : uploadStart,
upload_progress_handler : uploadProgress,
upload_error_handler : uploadError,
upload_success_handler : uploadSuccess,
upload_complete_handler : uploadComplete,
queue_complete_handler : queueComplete, // Queue plugin event // SWFObject settings
minimum_flash_version : "9.0.28",
swfupload_pre_load_handler : swfUploadPreLoad,
swfupload_load_failed_handler : swfUploadLoadFailed
};
swfu = new SWFUpload(settings);
};
//-->
</script> <%-- 上传并提交 --%>
<SCRIPT LANGUAGE="JavaScript">
//提交时验证表单
function submitCheck(){
try{
with(document.forms[0]){
var result = CheckNull(courseSubject, employeeName, lectureDate, hourArmy, miniteArmy, classroomName);
if(!result){
return false;
}
if (swfu.getStats().files_queued > 0) {
swfu.startUpload();
}else{
document.forms[0].submit();
}
}
return true;
}catch(e){
debug(e.message);
return false;
}
}
//删除已上传文件,修改页面需要
function delAffixFun(affixID){
with(document.forms[0]){
delAffixArr.value = delAffixArr.value + affixID + ",";
document.getElementById(affixID).style.display="none";
swfStats.successful_uploads--;
swfu.setStats(swfStats);
}
}
</SCRIPT> <%-- 页面元素 --%>
<div id="main">
<div id="list">
<table cellpadding="0" cellspacing="0" width="98%" border="0" align="center" class="tabular">
<tr>
<th>附件:</th>
<td colspan="3" valign="middle" >
<input type="hidden" name="affixListString"/>
<span id="spanButtonPlaceholder"></span>
<table id="idFileList" width="400" align="left" cellpadding="0" cellspacing="0" border="0" style="width:400px;overflow:hidden;border-style: dotted dashed solid double; "></table>
</td>
</tr>
</table>
<div id="freeFormButton">
<button type="button" name="addButton" onclick="submitCheck()"><div><b>保存</b></div></button>
<button type="button" onclick="window.close()"><div><b>取消</b></div></button>
</div>

Struts Form

  • 声明接收FormFile的对象
  • 声明获得附件最大限制的getter方法
/** 附件大小 */
private int theFileSize;
/** 附件 */
private FormFile uploadFileData; public void setTheFileSize(int theFileSize) {
this.theFileSize = theFileSize;
}
public int getTheFileSize() {
ManageSysConfigService manageSysConfigService = ManageSysConfigService.
getInstance();
try {
String strSize = manageSysConfigService.findParamValueByParamName(
SystemConstant.
MESSAGE_ATTACHMENT_SIZE);
if (strSize != null && !"".equals(strSize))
theFileSize = Integer.parseInt(strSize);
} catch (Exception ex) {
theFileSize = 500;
}
return theFileSize;
}
public FormFile getUploadFileData() {
return uploadFileData;
}
public void setUploadFileData(FormFile uploadFileData) {
this.uploadFileData = uploadFileData;
}

Struts Action

  • 从参数来获得上传的标识,进行上传的动作
  • 从参数中获得上传文件名,进行转码
  • 调用manageAffixService.createAttachmentUseSWF方法,解决MIME类型的问题
if ("upload".equals(flag_do)) {
//上传附件,得到新增附件ID
String aAccessoryID = addAffix(courseLecturesForm, request);
response.setContentType("text/html; charset=GBK");
response.getWriter().print("successed;affixListString="
+ aAccessoryID);
response.flushBuffer();
return null;
} //增加附件
String affixID = request.getParameter("affixListString"); /** 上传附件获取附件ID
* @param request
* @param classForm
* @return 附件ID
* @throws java.lang.Exception
*/
private String addAffix(CourseLecturesForm courseLecturesForm,
HttpServletRequest request) throws Exception { try {
FormFile formFile = courseLecturesForm.getUploadFileData();
//获取文件名称(避免中文乱码)
String fName = URLDecoder.decode(request.getParameter("aFileName"),
"UTF-8");
//读取上传人主机IP
String clientHostIP = request.getRemoteHost();
ManageAffixService manageAffixService = ManageAffixService.
getInstance();
//上传附件并得到附件ID
String affixID = manageAffixService.createAttachmentUseSWF(
formFile, fName, "讲座课附件", clientHostIP);
return affixID;
} catch (Exception ex) {
ex.printStackTrace();
throw ex;
}
}

Struts Service

  • 负责上传附件
    /**
* 生成附件,且将附件存储在附件表中
* @param file struts的formFile
* @param fileName 转码后的文件名(避免中文乱码)
* @param attachmentDesc 附件的简介
* @param clientIP 上传的ip地址
* @return String 附件ID
* @throws AppException
*/
public String createAttachmentUseSWF(FormFile file, String fileName, String attachmentDesc,
String clientIP) throws Exception {
try {
if (file == null || file.getFileSize() == 0) {
throw new AppException(String.valueOf(
"对不起,您上传的文件可能没有内容,请确认您上传的文件是否正确。(文件的大小要大于0个字节。)"));
} if (fileName.getBytes().length > 60) {
throw new AppException(String.valueOf(
"对不起,您上传的文件标题过长,请修改文件标题后重新上传。(文件标题不能超过60个字节。(包括扩展名,一个汉字以2个字节计算))"));
}
String suffix = ""; /**
* 取附件的后缀名
*/
if (fileName.indexOf(".") > -1) {
String[] names = fileName.split("\\.");
suffix = names[names.length - 1];
if (suffix.equalsIgnoreCase("exe")
|| suffix.equalsIgnoreCase("bat")
|| suffix.equalsIgnoreCase("cmd")
|| suffix.equalsIgnoreCase("com")
|| suffix.equalsIgnoreCase("sys")
|| suffix.equalsIgnoreCase("bin")
|| suffix.equalsIgnoreCase("dll")) {
throw new AppException("ERROR_AFFIX_FILETYPE_EXECUTE");
}
if (suffix.equalsIgnoreCase("asp")
|| suffix.equalsIgnoreCase("jsp")
|| suffix.equalsIgnoreCase("js")
|| suffix.equalsIgnoreCase("php")
|| suffix.equalsIgnoreCase("pl")
|| suffix.equalsIgnoreCase("aspx")
|| suffix.equalsIgnoreCase("css")
|| suffix.equalsIgnoreCase("htc")) {
throw new AppException("ERROR_AFFIX_FILETYPE_EXESCRIPT");
} }
int fileSize = file.getFileSize();
String fileID = "";
if (!suffix.equals("")) { //如果后缀名不为空
fileID = gds.util.UUIDGenerator.create("gds") + "." + suffix;
} else { //为空
fileID = gds.util.UUIDGenerator.create("gds");
}
AccessoryDTO accessoryDTO = new AccessoryDTO();
//获取SWF上传文件的MIME Type ,在mimetype.properties文件中维护
String pFilename = "/mimetype.properties"; // 构翠文件名
InputStream in = null;
Properties p = new Properties();
try {
in = getClass().getResourceAsStream(pFilename);
p.load(in); // 读入属使
} catch (Exception e) {
e.printStackTrace();
log.fatal("在系统的classpath下找不到mimetype.properties文件!" + e);
} finally {
try {
if (in != null) {
in.close();
}
} catch (Exception ex) {
log.error(ex);
}
}
String mimeType = "";
try {
mimeType = p.getProperty(suffix);
} catch (MissingResourceException e) {
mimeType = (new MimetypesFileTypeMap()).getContentType(fileName);
// e.printStackTrace();
}
ManageAffixService service = ManageAffixService.getInstance();
accessoryDTO.setAccessoryID(fileID);
accessoryDTO.setClientHostIP(clientIP);
accessoryDTO.setAccessoryName(fileName);
accessoryDTO.setFileSize(fileSize / 1024); //设置附件的大小,k为单位
accessoryDTO.setFileExt(suffix); //附件的扩展名
if (justMimeTypeExist(mimeType)) { //判断附件后缀名是否存在
accessoryDTO.setMimeType(mimeType);
} else {
accessoryDTO.setMimeType("其它");
}
accessoryDTO.setAccessoryDesc(attachmentDesc);
java.util.Date tmp = new Date();
accessoryDTO.setUploadTime(tmp);
SimpleDateFormat adf = new SimpleDateFormat("yyyy-MM");
String upTime = adf.format(tmp);
String upRoute = (gds.jap.common.AppSettingFactory.getInstance()).
getAppSetting("attachment.uploadDirectory");
File dirFile = new File(upRoute);
if (!dirFile.exists()) {
dirFile.mkdirs();
}
dirFile = new File(upRoute + upTime);
if (!dirFile.exists()) {
dirFile.mkdir();
}
java.io.OutputStream bos = null;
bos = new java.io.FileOutputStream(
upRoute + upTime + File.separator + fileID);
byte[] buffer = new byte[fileSize];
file.getInputStream().read(buffer, 0, fileSize);
bos.write(buffer);
service.addAccessory(accessoryDTO); //在数据库中增加附件
bos.close();
return fileID;
} catch (Exception ex) {
ex.printStackTrace();
throw ex;
}
} }