使用struts2和AJAX实现文件上传并显示进度条

使用struts2和AJAX实现文件上传并显示进度条
使用struts2和AJAX实现文件上传并显示进度条

使用struts2和AJAX实现文件上传并显示进度条

(2011-05-25 21:48:48)

转载▼

分类:java点滴

这个是刚进入公司,技术总监叫我做的东西,开始的确没有什么头绪,以前做的项目里只做过上传,下载。而且也只是方法调用。这个方法涉及到对common.fileupload.jar里一个方法的重写,并且要实现进度条。经过两天的奋斗,再浏览了各位前辈们的佳作,终于实现了以下的代码

需要导入的jar包如下:

jsp页面:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<%@ taglib prefix="s" uri="/struts-tags" %>

My JSP 'upload.jsp' starting page

method="post" target="uploadfile_iframe">



STRUTS配置文件:

"-//Apache Software Foundation//DTD Struts Configuration 2.1//EN"

"https://www.360docs.net/doc/f614937578.html,/dtds/struts-2.1.dtd">

name="myRequestParser" class="com.upload.MyRequestParseWrapper" scope="default" />

/file_box_upload.jsp

/file_box_upload.jsp

upload.java类:该类是采用servlet方法来存放文件

package com.upload;

import java.io.File;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.PrintWriter;

import java.util.List;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import https://www.360docs.net/doc/f614937578.html,mons.fileupload.FileItem;

import https://www.360docs.net/doc/f614937578.html,mons.fileupload.ProgressListener;

import https://www.360docs.net/doc/f614937578.html,mons.fileupload.disk.DiskFileItemFactory;

import https://www.360docs.net/doc/f614937578.html,mons.fileupload.servlet.ServletFileUpload;

import org.apache.log4j.Logger;

public class UploadFile {

private static final Logger LOG = Logger.getLogger(UploadFile.class);// LOG日志

@SuppressWarnings("unchecked")

public static void upload(HttpServletRequest request,

HttpServletResponse response) throws IOException {

https://www.360docs.net/doc/f614937578.html,("客户端提交类型: " + request.getContentType());

//判断文件类型,为空则报异常

if (request.getContentType() == null) {

throw new IOException(

"the request doesn't contain a multipart/form-data stream");

}

String key = request.getParameter("key");

Progress p = (Progress) request.getSession().getAttribute(key);

// 设置上传文件总大小

p.setLength(request.getContentLength());

https://www.360docs.net/doc/f614937578.html,("上传文件大小为 : " + p.getLength());

// 上传临时路径

String path = request.getSession().getServletContext().getRealPath("/file");

https://www.360docs.net/doc/f614937578.html,("上传临时路径 : " + path);

// 设置上传工厂

DiskFileItemFactory factory = new DiskFileItemFactory(); factory.setRepository(new File(path));

// 阀值,超过这个值才会写到临时目录

factory.setSizeThreshold(1024 * 1024 * 10);

ServletFileUpload upload = new ServletFileUpload(factory); // 最大上传限制 200M

upload.setSizeMax(1024 * 1024 * 200);

// 设置监听器监听上传进度

upload.setProgressListener(p);

try {

https://www.360docs.net/doc/f614937578.html,("解析上传文件....");

List items = upload.parseRequest(request);

https://www.360docs.net/doc/f614937578.html,("上传数据...");

for (FileItem item : items) {

// File destFile = new File(path,item.getFieldName()); // 非表单域

if (!item.isFormField()) {

https://www.360docs.net/doc/f614937578.html,("上传路径 : " + path );

FileOutputStream fos = new FileOutputStream(path

+ item.getName().substring(

item.getName().lastIndexOf("\\"),

item.getName().length()));

// 文件全在内存中

if (item.isInMemory()) {

fos.write(item.get());

p.setComplete(true);

} else {

InputStream is = item.getInputStream();

byte[] buffer = new byte[1024];

int len;

while ((len = is.read(buffer)) > 0) {

fos.write(buffer, 0, len);

}

is.close();

}

fos.close();

https://www.360docs.net/doc/f614937578.html,("完成上传文件!");

item.delete();

https://www.360docs.net/doc/f614937578.html,("删除临时文件!");

p.setComplete(true);

https://www.360docs.net/doc/f614937578.html,("更新progress对象状态为完成状态!");

}

}

} catch (Exception e) {

LOG.error("上传文件出现异常, 错误原因 : " + e.getMessage());

// 发生错误,进度信息对象设置为完成状态

p.setComplete(true);

request.getSession().removeAttribute(key);

}

}

public static void execClientScript(HttpServletResponse resposne, String script) throws IOException {

PrintWriter out = resposne.getWriter();

out.println(""); // fix ie problem

out.println("------------------------------------------------------"); out.println("------------------------------------------------------"); out.println("------------------------------------------------------"); out.println("------------------------------------------------------"); out.println("------------------------------------------------------"); out.flush();

}

public static class Progress implements ProgressListener {

// 文件总长度

private long length = 0;

// 已上传的文件长度

private long currentLength = 0;

// 上传是否完成

private boolean isComplete = false;

@Override

public void update(long bytesRead, long contentLength, int items) {

this.currentLength = bytesRead;

}

public long getLength() {

return length;

}

public long getCurrentLength() {

return currentLength;

}

public boolean isComplete() {

return isComplete;

}

public void setLength(long length) {

this.length = length;

}

public void setCurrentLength(long currentLength) {

this.currentLength = currentLength;

}

public void setComplete(boolean isComplete) {

this.isComplete = isComplete;

}

}

}

MyRequestParseWrapper.java重写源文件方法,不要其一次上传package com.upload;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;

import org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest; public class MyRequestParseWrapper extends JakartaMultiPartRequest {

@Override

public void parse(HttpServletRequest servletRequest, String saveDir)

throws IOException {

// 什么也不做---

}

}

FileService.java类:这个类是一些方法提取出来写了,在action里直接调用

package com.upload;

import java.io.InputStream;

import java.io.OutputStream;

import java.io.FileOutputStream;

import javax.activation.DataHandler;

public class FileService {

// 使用byte[]类型参数上传二进制文件

public boolean uploadWithByte(byte[] file, String filename) {

FileOutputStream fos = null;

try {

fos = new FileOutputStream(filename);

fos.write(file);

fos.close();

} catch (Exception e) {

return false;

} finally {

if (fos != null) {

try {

fos.close();

} catch (Exception e) {

}

}

}

return true;

}

private void writeInputStreamToFile(InputStream is, OutputStream os)

throws Exception {

int n = 0;

byte[] buffer = new byte[8192];

while ((n = is.read(buffer)) > 0) {

os.write(buffer, 0, n);

}

}

// 使用DataHandler类型参数上传文件

public boolean uploadWithDataHandler(DataHandler file, String filename) { FileOutputStream fos = null;

try {

fos = new FileOutputStream(filename);

// 可通过DataHandler类的getInputStream方法读取上传数据

writeInputStreamToFile(file.getInputStream(), fos);

fos.close();

} catch (Exception e) {

return false;

} finally {

if (fos != null) {

try {

fos.close();

} catch (Exception e) {

}

}

}

return true;

}

}

FileAction.java 这个实现进度条的action,我认为是最重要的一个类package com.upload;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionSupport;

import com.upload.UploadFile;

import com.upload.UploadFile.Progress;

public class FileAction extends ActionSupport {

private static final long serialVersionUID = 6649027352616232244L; private FileService fileService;

public String preupload() {

return SUCCESS;

}

public String uploadfile() {

try {

https://www.360docs.net/doc/f614937578.html,("文件上传操作开始");

HttpServletResponse response = ServletActionContext.getResponse(); HttpServletRequest request = ServletActionContext.getRequest();

UploadFile.upload(request, response);

} catch (IOException e) {

// LOG.error("上传文件发生异常,错误原因 : " + e.getMessage()); }

return null;

}

public String progress() {

System.out.println("begin");

https://www.360docs.net/doc/f614937578.html,("文件上传进度监测开始");

HttpServletResponse response = ServletActionContext.getResponse(); HttpServletRequest request = ServletActionContext.getRequest();

String callback1 = request.getParameter("callback1");

String callback2 = request.getParameter("callback2");

// 缓存progress对象的key值

String key = Integer.toString(request.hashCode());

// 新建当前上传文件的进度信息对象

Progress p = new Progress();

// 缓存progress对象

request.getSession().setAttribute(key, p);

response.setContentType("text/html;charset=UTF-8");

response.setHeader("pragma", "no-cache");

response.setHeader("cache-control", "no-cache");

response.setHeader("expires", "0");

try {

https://www.360docs.net/doc/f614937578.html,("文件上传进度监测开始--------");

UploadFile.execClientScript(response, callback1 + "(" + key + ")");

long temp = 0l;

while (!p.isComplete()) {

if (temp != p.getCurrentLength()) {

temp = p.getCurrentLength();

// 向客户端显示进度

UploadFile.execClientScript(response, callback2 + "("

+ p.getCurrentLength() + "," + p.getLength() + ")");

//https://www.360docs.net/doc/f614937578.html,("progress的状态:" + p.isComplete());

} else {

//https://www.360docs.net/doc/f614937578.html,("progress的状态:" + p.isComplete());

//https://www.360docs.net/doc/f614937578.html,("progress上传的数据量:+ " + p.getCurrentLength());

// 上传进度没有变化时候,不向客户端写数据,写数据过于频繁会让chrome没响应 Thread.sleep(100);

}

}

} catch (Exception e) {

LOG.error("调用客户端脚本错误,原因:" + e.getMessage());

p.setComplete(true);

}

try {

UploadFile.execClientScript(response, callback2 + "("

+ p.getCurrentLength() + "," + p.getLength() + ")");

} catch (Exception e) {

p.setComplete(true);

}

request.getSession().removeAttribute(key);

https://www.360docs.net/doc/f614937578.html,("删除progress对象的session key");

return null;

}

public FileService getFileService() {

return fileService;

}

public void setFileService(FileService fileService) {

this.fileService = fileService;

}

}

download.action:这类是从临时文件中下载文件给我们实际上传的目录package com.upload;

import java.io.InputStream;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionSupport;

public class DownloadAction extends ActionSupport

{

private static final long serialVersionUID = 3350848163772547204L;

public InputStream getDownloadFile()

{

return ServletActionContext.getServletContext().getResourceAsStream( "/file/aa.txt");

}

@Override

public String execute() throws Exception

{

return SUCCESS;

}

}

Java多方式实现文件上传

在Struts 2中实现文件上传 前一阵子有些朋友在电子邮件中问关于Struts 2实现文件上传的问题,所以今天我们就来讨论一下这个问题。 实现原理 Struts 2是通过Commons FileUpload文件上传。Commons FileUpload通过将HTTP的数据保存到临时文件夹,然后Struts使用fileUpload拦截器将文件绑定到Action的实例中。从而我们就能够以本地文件方式的操作浏览器上传的文件。 具体实现 前段时间Apache发布了Struts 2.0.6 GA,所以本文的实现是以该版本的Struts 作为框架的。以下是例子所依赖类包的列表: 清单1 依赖类包的列表 首先,创建文件上传页面FileUpload.jsp,内容如下: <% @ page language = " java " contentType = " text/html; charset=utf-8 " pageEncodi ng = " utf-8 " %> <% @ taglib prefix = " s " uri = " /struts-tags " %> Struts 2 File Upload

基于Struts2 Result Type为chain 的Action之间数据传递

chain:基本用途是构造成一条动作链。前一个Action将控制权转交给后一个Action,而前一个Action的状态在后一个Action里仍然保持着。 我现在有一个场景,FirstAction 通过chain的方式,将控制权交给SecondAction。FirstAction对应的页面代码为first.ftl,SecondAction对应的页面代码为second.ftl。 假设我们的FirstAction如下定义: public class SecondAction extends ActionSupport{ private CustomUser user = null; public String execute() throws Exception { // 利用user做事情或显示在页面上 } // getter setter } 意思很明确了,通过first.ftl的输入,到DB中或其他,生成了我们的CustomUser对象,这个CustomUser对象将要在SecondAction使用。 于是我们想到了要配置FirstAction 的name为toSecond的Result type为chain,将生成的CustomUser对象传递到SecondAction中, 我们也这样做了,但是经过调试,发现在SecondAction中没有得到FirstAction中的CustomUser对象。 SecondAction是这样实现的: public class SecondAction extends ActionSupport{ private CustomUser user = null; public String execute() throws Exception { // 利用user做事情或显示在页面上 } // getter setter } 看一下ChainingInterceptor.java的实现,发现有这样的注释: An interceptor that copies all the properties of every object in the value stack to t he currently executing object.

struts2 strus.xml中result类型及含义

struts2strus.xml中result类型及含义 一个提交到服务器的处理通常可以分为两个阶段,第一个阶段查询服务器状态(查询或者更新数据库),第二个阶段选择一个合适的结果页面其返回给用户(这里要讲的Result的内容)。 Struts2提供了对不同种类返回结果的支持,常见的有JSP,FreeMarker,Velocity等。 Struts2支持的不同类型的返回结果为: 名字说明 Chain Result用来处理Action链 Dispatcher Result用来转向页面,通常处理JSP FreeMarker Result处理FreeMarker模板 HttpHeader Result用来控制特殊的Http行为 Redirect Result重定向到一个URL Redirect Action Result重定向到一个Action Stream Result向浏览器发送InputSream对象,通常用来处 理文件下载 Velocity Result处理Velocity模板 XLS Result处理XML/XLST模板 PlainText Result显示原始文件内容,例如文件源代码 结合Tile使用 S2PLUGINS:Tiles Result 另外第三方的Result类型还包括JasperReports Plugin,专门用来处理JasperReport类型的报表输出。 在struts-default.xml文件中已经有了对于所有类型Result的定义:

Struts2配置文件通配符的使用说明

Struts2配置文件中使用通配符收藏 形式一:调用相同Action中的不同方法 /login.jsp /error.jsp /welcome.jsp 其中表达式{1}的值name属性值中第一个*的值。 如果用户请求的URL为loginAction.action,则调用Jcuckoo.LoginRegistAction中的login方法; 如果用户请求的URL为registerAction.action,则调用Jcuckoo.LoginRegistAction中的register方法;形式二:通过匹配,调用不同的Action的execute方法 /login.jsp /error.jsp /welcome.jsp 上面没有出现method属性,故默认调用对应的execute方法 如果用户请求的URL为LoginAction.action,则调用Jcuckoo.LoginAction中的execute方法; 如果用户请求的URL为RegisterAction.action,则调用Jcuckoo.RegisterAction中的execute方法; 形式三:动态结果 /input.jsp /{1}.jsp 当处理结果是input时,会转到/input.jsp页面

JAVA之struts2+ajax实现echats柱状图

说明:本实例使用的是echart3,jquery1.8.1 1)struts的web.xml配置代码如下: struts2 index.html index.htm index.jsp default.html default.htm default.jsp struts2 org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecu teFilter struts2 /* 2)struts.xml代码