今天下午安排了一个任务:要实现多文件上传,也就是批量上传文件。相信单个文件上传很多人都实现过,批量上传也有不少人实现过,我之前批量上传的做法是利用js或jquery来动态添加删除<input type="file" name="file" />的。感觉在用户体验上也不是很好,于是在网上google一把,发现大家常用的是swfupload.swf这个插件,网上也有类似的例子,但也发现了GooUploader这个插件,它是基于swfupload.swf,也就是底层封装了改插件,同时可以实现无刷新。于是在网上google一把,下了下来。下下来的可以直接放在tomcat运行了,不过它后台是基于servlet实现的。代码如下:
通过反编译工具查看的,它的底层是基于apache的两个有名的常用的组件:commons-fileupload-1.2.1和commons-io-1.4.jar实现的。
- package servlet;
- import java.io.BufferedInputStream;
- import java.io.BufferedOutputStream;
- import java.io.File;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.io.PrintStream;
- import java.io.PrintWriter;
- import javax.servlet.Servlet;
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import org.apache.commons.fileupload.FileItemIterator;
- import org.apache.commons.fileupload.FileItemStream;
- import org.apache.commons.fileupload.disk.DiskFileItemFactory;
- import org.apache.commons.fileupload.servlet.ServletFileUpload;
- import org.apache.commons.fileupload.util.Streams;
- public class UploadFileServlet extends HttpServlet
- implements Servlet
- {
- File tmpDir = null;
- File saveDir = null;
- protected void doGet(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException
- {
- doPost(request, response);
- }
- protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- try {
- request.setCharacterEncoding("UTF-8");
- if (ServletFileUpload.isMultipartContent(request)) {
- DiskFileItemFactory dff = new DiskFileItemFactory();
- dff.setRepository(this.tmpDir);
- dff.setSizeThreshold(1024000);
- ServletFileUpload sfu = new ServletFileUpload(dff);
- sfu.setFileSizeMax(109999999L);
- sfu.setSizeMax(999999999L);
- FileItemIterator fii = sfu.getItemIterator(request);
- while (fii.hasNext()) {
- FileItemStream fis = fii.next();
- if ((!fis.isFormField()) && (fis.getName().length() > 0)) {
- System.out.println(fis.getName());
- String fileName = fis.getName();
- BufferedInputStream in = new BufferedInputStream(fis.openStream());
- BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(new File("f:\\nokia\\" + fileName)));
- Streams.copy(in, out, true);
- }
- }
- response.getWriter().println("File upload successfully!!!");
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- public void init()
- throws ServletException
- {
- super.init();
- String tmpPath = "f:\\nokia\\";
- String savePath = "f:\\nokia\\";
- this.tmpDir = new File(tmpPath);
- this.saveDir = new File(savePath);
- if (!this.tmpDir.isDirectory())
- this.tmpDir.mkdir();
- if (!this.saveDir.isDirectory())
- this.saveDir.mkdir();
- System.out.print("UploadFileServlet init");
- }
- }
主要就是这个servlet就实现了。由于我的项目是用ssh2,于是就考虑用struts2来实现,废话少说了,
先看效果图:
主要代码如下:
index.jsp
- <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
- <%
- 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>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <title>文件上传控件GooUploader</title>
- <link rel="stylesheet" type="text/css" href="codebase/GooUploader.css"/>
- <script type="text/javascript" src="codebase/jquery-1.3.2.min.js"></script>
- <script type="text/javascript" src="codebase/GooUploader.js"></script>
- <script type="text/javascript" src="codebase/swfupload/swfupload.js"></script>
- <script type="text/javascript">
- var demo;
- var post_params = {session_id:"f1423rwe543t4wrtwerwe"};
- var property={
- width:300,
- height:200,
- multiple:true,
- //file_post_name : "Filedata",
- //file_types:"*.jpg;*.gif",
- // file_types_description: "Web Image Files",
- // post_params:post_params,
- btn_add_text:"添加",
- btn_up_text:"上传",
- btn_cancel_text:"放弃",
- btn_clean_text:"清空",
- op_del_text:"单项删除",
- op_up_text:"单项上传",
- op_fail_text:"上传失败",
- op_ok_text:"上传成功",
- op_no_text:"取消上传",
- upload_url:"uploadImage.action",
- flash_url :"codebase/swfupload.swf"
- };
- $(document).ready(function(){
- demo=$.createGooUploader($("#demo"),property)
- });
- </script>
- </head>
- <body>
- <br/>
- <br/>
- <div id="demo"></div>
- </body>
- </html>
注意: * file_post_name : "Filedata"该参数设置了POST信息中上传文件的name值(类似传统Form中设置了<input type="file" name="uploadImg"/>的name属性)。
* 注意:在Linux下面此参数设置无效,接收的name总为Filedata,因此为了保证最大的兼容性,建议此参数使用默认值。查到这个信息我花了3个小时搜索,最后在文档中找到了,这是用struts2实现的关键。
UploadAction.java
- package com.test;
- import java.io.BufferedInputStream;
- import java.io.BufferedOutputStream;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.FileOutputStream;
- import java.io.InputStream;
- import java.io.OutputStream;
- import java.util.List;
- import javax.servlet.ServletContext;
- import javax.servlet.http.HttpServletRequest;
- import org.apache.commons.io.FileUtils;
- import org.apache.struts2.ServletActionContext;
- import com.opensymphony.xwork2.ActionSupport;
- /**
- * @author fish
- */
- public class UploadAction extends ActionSupport
- {
- private List<File> Filedata; // 默认的客户端文件对象,命名不符合java规范fileData
- private List<String> FiledataFileName; // 客户端文件名
- private List<String> imageContentType; // 客户端文件名类型
- public List<File> getFiledata()
- {
- return Filedata;
- }
- public void setFiledata(List<File> filedata)
- {
- Filedata = filedata;
- }
- public List<String> getFiledataFileName()
- {
- return FiledataFileName;
- }
- public void setFiledataFileName(List<String> filedataFileName)
- {
- FiledataFileName = filedataFileName;
- }
- public List<String> getImageContentType()
- {
- return imageContentType;
- }
- public void setImageContentType(List<String> imageContentType)
- {
- this.imageContentType = imageContentType;
- }
- @Override
- public String execute() throws Exception
- {
- if (Filedata == null || Filedata.size() == 0)
- {
- return null;
- }
- for (int i = 0; i < Filedata.size(); ++i)
- {
- String fileName = FiledataFileName.get(i); // 文件真名
- long length = Filedata.get(i).length(); // 文件的真实大小
- long time = System.currentTimeMillis();
- // 将上传的文件保存到服务器的硬盘上
- InputStream is = new BufferedInputStream(new FileInputStream(Filedata.get(i)));
- HttpServletRequest request = ServletActionContext.getRequest(); // 获得ServletRequest对象
- //request.getRealPath("/")已不建议使用,改为this.getServletContext().getRealPath("/")
- System.out.println("path:"+ServletActionContext.getServletContext().getRealPath("/"));
- File tempFile = new File(ServletActionContext.getServletContext().getRealPath("/uploadimages")+File.separator+fileName);
- FileUtils.forceMkdir(tempFile.getParentFile()); // 创建上传文件所在的父目录
- OutputStream os = new BufferedOutputStream( new FileOutputStream(tempFile));
- int len = 0;
- byte[] buffer = new byte[500];
- while (-1 != (len = is.read(buffer)))
- {
- os.write(buffer, 0, len);
- }
- is.close();
- os.flush();
- os.close();
- }
- return null;
- }
- }
struts.xml
- <?xml version="1.0" encoding="UTF-8" ?>
- <!DOCTYPE struts PUBLIC
- "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
- "http://struts.apache.org/dtds/struts-2.0.dtd">
- <struts>
- <constant name="struts.multipart.maxSize" value="100000000000"></constant>
- <package name="upload" extends="struts-default">
- <action name="uploadImage" class="com.test.UploadAction"></action>
- </package>
- </struts>
这样就搞定了,说难也不难,说易也不易,关键是要找到类似传统Form中设置了<input type="file" name="uploadImg"/>的name属性,就可以了。若想用servlet实现,直接用源码的例子就可以了。
动态传参:
- post_params={value:value};
- demo.$swfUpload.setPostParams(post_params);