SWFUpload初体验 For Struts1.x

         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多文件上传

开始配置

准备工作:

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

SWFUpload v2.2.0.1 Coreswfupload.js

SWFUpload v2.2.0.1 CoreFlashswfupload.swf

SWFUpload v2.2.0.1 Samplesdemossimpledemojsfileprogress.js

SWFUpload v2.2.0.1 Samplesdemossimpledemojshandlers.js

SWFUpload v2.2.0.1 Samplesdemossimpledemojsswfupload.queue.js

放在指定文件夹中

deploymediaswfupload

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("您选择的文件超过文件数量限制。
" + (message === 0 ? "您已达到上传限制。" :  (message > 1 ? "您可以再添加 " + message + " 个文件。" : "您不能再添加文件。")));
            return;
        }
        var errInfo = "添加失败
原因:";
        /* 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 + "
文件:" + 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_ "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="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;
        }
    }

}
原文地址:https://www.cnblogs.com/leemoby/p/3468698.html