SWFUpload详解 java后台接收实例(包括传参问题)

一、简介和示例

SWFUpload is a small JavaScript/Flash library to get the best of both worlds. It features the great upload capabilities of Flash and the accessibility and ease of HTML/CSS。

官方站点:http://www.swfupload.org/

简单来说,swfupload这个上传库是可以显示上传进度以及上传速度等上传信息。一般实现这种上传体验有2种方式,一种是异步上传,在服务器端边接收数据边往session写入接收的字节数和进度数据,然后客户端轮询这个记录在session的进度数据并回显到页面。第二种方式就是采用flash来上传,也就是swfupload所采用的方式,在发送过程中将发送的相关状态数据回传到js的函数中处理。

二、参数说明

原理是很明显易懂的,关键是flash和javascript的通讯部分,在文件上传的各个状态都会有javascript和flash函数的相互回调。目前主要研究了上传单个文件的上传逻辑,swfupload支持多个文件上传的,不过核心的逻辑应该是没有太多的变化。swfupload用一个队列来管理多个文件上传的,因为在传入的参数中会有一些队列和文件上传数量相关的参数。

在其核心的JavaScript文件swfupload.js定义的状态码以及从flash传递到js的文件对象:

	//文件对象
	file = {
	    "id":SWFUpload_0_0,
	    "index":0,
	    "filestatus":-1,
	    "name":vim-cheat-sheet-diagram.png,
	    "size":317949,
	    "type":"",
	    "creationdate":Fri Jan 16 1970 00:08:13 GMT+0800 (CST),
	    "modficationdate":Fri Jan 16 1970 00:08:13 GMT+0800 (CST),
	    "post": {}
	}
	
	//文件队列错误码
	SWFUpload.QUEUE_ERROR = {
	    QUEUE_LIMIT_EXCEEDED            : -100,
	    FILE_EXCEEDS_SIZE_LIMIT         : -110,
	    ZERO_BYTE_FILE                  : -120,
	    INVALID_FILETYPE                : -130
	};
	
	//上传错误码
	SWFUpload.UPLOAD_ERROR = {
	    HTTP_ERROR                      : -200,
	    MISSING_UPLOAD_URL              : -210,
	    IO_ERROR                        : -220,
	    SECURITY_ERROR                  : -230,
	    UPLOAD_LIMIT_EXCEEDED           : -240,
	    UPLOAD_FAILED                   : -250,
	    SPECIFIED_FILE_ID_NOT_FOUND     : -260,
	    FILE_VALIDATION_FAILED          : -270,
	    FILE_CANCELLED                  : -280,
	    UPLOAD_STOPPED                  : -290
	};
	
	//文件状态
	SWFUpload.FILE_STATUS = {
	    QUEUED       : -1,
	    IN_PROGRESS  : -2,
	    ERROR        : -3,
	    COMPLETE     : -4,
	    CANCELLED    : -5
	};
	
	//按钮的动作
	SWFUpload.BUTTON_ACTION = {
	    SELECT_FILE  : -100,
	    SELECT_FILES : -110,
	    START_UPLOAD : -120
	};

1. 事件处理函数

事件函数触发时间参数
swfupload_loaded_handler在flash初始化完成之后没有参数
file_dialog_start_handler当用户点击上传按钮,在打开文件浏览窗口之前没有参数
file_queued_handler用户成功地选择了文件,在file_dialog_complete_handler事件之前触发。如果选择了多个文件,则触发多次file文件对象
file_queue_error_handler文件上传数量、类型、大小不符合时file文件对象、错误码、从flash中返回的错误信息
file_dialog_complete_handler在用户成功了选择了文件后,在所有file_queued_handler之后触发选择文件的数量、加入了文件队列的文件数量、在当前文件队列总共的文件数量
upload_start_handler用户点击了提交按钮,开始把文件上传到服务器file文件对象
upload_progress_handler刚打开与服务器的连接与文件上传过程中file文件对象、已经上传的字节数、总共要上传的字节数
upload_error_handler上传失败时file文件对象、错误码、从flash中返回的错误信息
upload_success_handler文件上传成功或者等待服务器数据返回超时file文件对象、服务器返回的数据、服务器是否有返回数据
upload_complete_handler上传完成时,在upload_success_handler之后触发file文件对象
debug_handler调用SWFUpload对象的debug()函数时swfupload对象和其初始化的参数

2. 其他重要参数

参数名意义说明
upload_url要上传到的服务器地址 
file_post_name上传到服务器中文件内容对应的key 
flash_urlflash元素的url 
custom_settings自定义的参数,可以在事件处理函数中获取得到dict类型
button_placeholder_idflash的上传按钮显示在html的位置,此名称的元素会被替换成object元素span即可

三、上传逻辑

下面是用graphviz画出来的流程图,图比较大,不过看得舒服:)
1. 如上面的示例代码所示,在javascript代码中首先要创建一个SWFUpload的javascript对象,这个对象创建的初始化逻辑如下(箭头表示逻辑和流程的走向):
js_swfupload
2. 当javascript将object元素添加到html页面的元素中时,即初始化flash中的元素:
flash_swfupload
3.用户点击上传的按钮,准备选择文件时,这个已经绑定了按钮的点击事件,而这个按钮不是input而是一个flash的元素:
open_filebrowser
4.用户选择完文件后:
select_file
5. 用户点击提交按钮,文件开始上传到服务器:
submit_upload
6. 文件上传过程中的一些事件处理逻辑:
upload_events


实例代码(注意要在服务器部署之后下浏览才有效
上代码:
一、前台页面index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="GB18030"%>

	<%
	String path = request.getContextPath();
	String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
	%>
	 
	<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
	<html>
	  <head>
	    <base href="<%=basePath%>">
	     
	    <title>文件上传swfupload使用</title>
	    <meta http-equiv="pragma" content="no-cache">
	    <meta http-equiv="cache-control" content="no-cache">
	    <meta http-equiv="expires" content="0">   
	    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
	    <meta http-equiv="description" content="This is my page">
	    <!--
	    <link rel="stylesheet" type="text/css" href="styles.css">
	    -->
	    <link href="<%=basePath%>css/default.css" rel="stylesheet" type="text/css" />
	    <script type="text/javascript" src="<%=basePath%>swfupload/swfupload.js"></script>
	    <script type="text/javascript" src="<%=basePath%>swfupload/swfupload.queue.js"></script>
	    <script type="text/javascript" src="<%=basePath%>js/fileprogress.js"></script>
	    <script type="text/javascript" src="<%=basePath%>js/handlers.js"></script>
	     
	     
	    <script type="text/javascript">
	    var swfu;
	 
	    window.onload = function () {
	        var settings = {
	            flash_url : "<%=basePath%>swfupload/swfupload.swf",
	            flash9_url : "<%=basePath%>swfupload/swfupload_fp9.swf",
	            upload_url: "<%=basePath%>upload",
	            post_params: {
	                "hello" : "Here I Am",
	                "name" : "张三"
	            },
	            file_size_limit : "100 MB",
	            file_types : "*.*",
	            file_types_description : "All Files",
	            file_upload_limit : 100,
	            file_queue_limit : 0,
	            custom_settings : {
	                progressTarget : "fsUploadProgress",
	                cancelButtonId : "btnCancel"
	            },
	            debug: true,
	            use_query_string : true,//要传递参数,必须配置,可以从后台取到参数,应该还有其他方式,如post方式,未了解
	             
	            // Button Settings
	            button_image_url : "<%=basePath%>images/TestImageNoText_65x29.png",
	            button_placeholder_id : "spanButtonPlaceholder",
	            button_width: 61,
	            button_height: 22,
	            button_text: '浏览',
	            button_text_style: ".spanButtonPlaceholder { font-size: 12; }",
	            button_text_left_padding: 12,
	            button_text_top_padding: 3,
	 
	            // The event handler functions are defined in handlers.js
	            //swfupload_preload_handler : preLoad,
	            //swfupload_load_failed_handler : loadFailed,
	            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
	             
	        };
	 
	        swfu = new SWFUpload(settings);
	    }
	    </script>
	  </head>
	  <body>
	        <div class="fieldset flash" id="fsUploadProgress">
	            <span class="legend">文件列表:</span>
	            </div>
	        <div id="divStatus">上传了0个文件</div>
	     
	    <div class="flash" id="fsUploadProgress">
	    </div>
	    <div style="padding-left: 5px;">
	        <span id="spanButtonPlaceholder"></span>
	        <input id="btnCancel" type="button" value="取消" οnclick="cancelQueue(upload);" disabled="disabled" style="margin-left: 2px; height: 22px; font-size: 8pt;" />
	    </div>
	     
	    <!-- 上传文件列表 -->
	    <div class="fileList" id="fileList">
	    </div>
	     
	  </body>
	</html>
二、前台接收后台返回数据的位置 --handler.js-只需要找到该位置,进行修改就可以了
function uploadSuccess(file, serverData) {
	    try {
	        var progress = new FileProgress(file, this.customSettings.progressTarget);
	        progress.setComplete();
	        progress.setStatus("上传完成.");
	        progress.toggleCancel(false);
	        alert(serverData);
	         
	        //后台传递回来的内容
	        var serdata = document.getElementById("fileList");
	        serdata.innerHTML = serverData;
	         
	    } catch (ex) {
	        this.debug(ex);
	    }
	}
三、后台servlet-Upload.java,下边只列出了用到的doPost()方法,其他内容都没有变化
public void doPost(HttpServletRequest request, HttpServletResponse response)
	            throws ServletException, IOException {
	 
	        //接收参数
	        String hello = request.getParameter("hello");
	        String name = request.getParameter("name");
	        name = new String(name.getBytes("ISO-8859-1"),"UTF-8");//字符编码问题,可以通过前台encoding后台再解析
	         
	        System.out.println("接收参数,hello="+hello+",name="+name);
	     
	        String path1 = request.getRequestURI()+"/files";
	        System.out.println("____________request.getRequestURI():"+path1);
	        String path2 = request.getSession().getServletContext().getRealPath("/");
	        System.out.println("_________path2:"+path2);
	     
	        List<FileEntity> fileList;
	        fileList = (List)request.getAttribute("fileList");
	        if(fileList==null)
	            fileList = new ArrayList<FileEntity>();
	         
	        //接收上传文件
	        String uploadSign = request.getParameter("upload");
	          String rootPath = request.getParameter("rootPath");
	          String path = request.getParameter("path");
	          if(rootPath == null) rootPath = "";
	            rootPath = rootPath.trim();
	          if(rootPath.equals("")){
	            //rootPath = application.getRealPath("/swfupload/files");//自由修改处二:指定服务器固定文件
	              rootPath = path2+"/files";
	          }
	 
	          if(path == null) {
	            path = rootPath;
	          }else{
	            path = new String(Base64.decodeBase64(path.getBytes()));
	          }
	          System.out.println(path+"...path.getBytes():"+path.getBytes());
	          uploadSign = "1";
	          //上传操作
	          if(null != uploadSign && !"".equals(uploadSign)){
	              FileItemFactory factory = new DiskFileItemFactory();
	              ServletFileUpload upload = new ServletFileUpload(factory);
	              //upload.setHeaderEncoding("UTF-8");
	              try{
	                  List items = upload.parseRequest(request);
	                  if(null != items){
	                      Iterator itr = items.iterator();
	                      int i = 0;
	                      while(itr.hasNext()){
	                          FileItem item = (FileItem)itr.next();
	                          FileEntity file = new FileEntity();//_____________________
	                          if(item.isFormField()){
	                              continue;
	                          }else{
	                              //自由修改处三:可修改上传后的文件命名方式
	                              SimpleDateFormat sdf=new SimpleDateFormat("yyyyMMddkkmmss");//以当前精确到秒的日期为上传的文件的文件名
	                              SimpleDateFormat sdd=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	                              String type = item.getName().split("\\.")[1];//获取文件类型
	                               
	                              System.out.println("——————————————————文件名称:"+item.getName());
	                              System.out.println("从GBK转到UTF-8输出:"+new String(item.getName().getBytes("GBK"),"UTF-8"));
	                              File savedFile = new File(path,sdf.format(new Date())+"."+type);
	                               
	                              //把文件放到列表中,在前台显示
	                              System.out.println("__________________服务器上对应的文件名称:"+sdf.format(new Date())+"."+type);
	                              System.out.println("__________________完整路径:"+path1+"/"+sdf.format(new Date())+"."+type);
	                              file.setId(sdf.format(new Date()));
	                              file.setDate(sdd.format(new Date()));
	                              file.setFilename(item.getName());
	                              file.setFilepath(path1+"/"+sdf.format(new Date())+"."+type);
	                              file.setFilesize(item.getSize()+"");
	                              file.setFiletype(type);
	                              file.setMark("0");
	                              fileList.add(file);
	                               
	                              item.write(savedFile);
	                          }
	                      }
	                  }
	              }catch(Exception e){
	                  e.printStackTrace();
	              }
	          }
	         
	         
	        response.setContentType("text/html");
	        response.setCharacterEncoding("UTF-8");
	        PrintWriter out = response.getWriter();
	        if(fileList!=null){
	            for(int i=0;i<fileList.size();i++){
	                FileEntity file = (FileEntity)fileList.get(i);
	                //out.println("文件:"+ new String(file.getFilename().getBytes("GBK"),"UTF-8")+",文件路径:"+file.getFilepath());
	                out.println("文件:"+ new String(file.getFilename().getBytes("GBK"),"UTF-8")+",上传成功!");
	            }
	        }
	    }
四、自定义的一个文件类FileEntity.java,测试时全部用的String类型
package com.swfupload.entity;
	public class FileEntity {
	    private String id;
	    private String belong;
	    private String filename;
	    private String filepath;
	    private String filetype;
	    private String filesize;
	    private String date;
	    private String mark;
	     
	    public FileEntity(){}
	     
	    public String getId() {
	        return id;
	    }
	    public void setId(String id) {
	        this.id = id;
	    }
	    public String getBelong() {
	        return belong;
	    }
	    public void setBelong(String belong) {
	        this.belong = belong;
	    }
	    public String getFilename() {
	        return filename;
	    }
	    public void setFilename(String filename) {
	        this.filename = filename;
	    }
	    public String getFilepath() {
	        return filepath;
	    }
	    public void setFilepath(String filepath) {
	        this.filepath = filepath;
	    }
	    public String getFiletype() {
	        return filetype;
	    }
	    public void setFiletype(String filetype) {
	        this.filetype = filetype;
	    }
	    public String getFilesize() {
	        return filesize;
	    }
	    public void setFilesize(String filesize) {
	        this.filesize = filesize;
	    }
	    public String getDate() {
	        return date;
	    }
	    public void setDate(String date) {
	        this.date = date;
	    }
	    public String getMark() {
	        return mark;
	    }
	    public void setMark(String mark) {
	        this.mark = mark;
	    }
	     
	    public static void main(String[] agrs){
	        String str="";
	        System.out.println(str);
	    }
	}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值