• 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;
            }
        }
    
    }
  • 相关阅读:
    ASP.NET Core中的Action的返回值类型
    ASP.NET Core中的Controller
    ASP.NET Core Authentication and Authorization
    ASP.NET Core
    ASP.NET Core ActionFilter引发的一个EF异常
    使用Github Packages功能上传nuget包到Github
    「每日五分钟,玩转JVM」:线程共享区
    JVM(二):画骨
    Spring Boot 2.x (十八):邮件服务一文打尽
    一道面试题
  • 原文地址:https://www.cnblogs.com/leemoby/p/3468698.html
Copyright © 2020-2023  润新知