Struts2下利用JSON结合jQuery Form插件实现文件上传的问题与解决办法

本文介绍如何使用Struts2与jQuery结合Ajax技术实现文件上传功能,详细解析了利用jQuery form插件进行文件上传的过程及遇到的问题解决方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这两天要实现一个文件上传的功能。

开发环境是:服务器端Struts2,客户端jQuery,需要使用Ajax来实现,我在用Struts2开发Ajax应用时,都是基于JSON来实现的。

 

理论上文件上传是无法用Ajax来实现的:ajax基于javascript和xmlhtttp,其与服务器通信都是通过传递字符串。另外出于安全考虑,javascript是不能操作文件的,因此从理论上来说javascript是无法实现文件上传的。

 

实际上只能实现一种无刷新文件上传,从实现效果上类似于Ajax的无刷新与服务器进行通信。

 

其原理是:给file控件所在的form加上 target 属性,将返回结果页面定向到一个隐藏的 iframe。

 

在具体的实现上,我使用了jQuery的form插件来完成,该插件对文件上传的功能进行了封装,其实现原理也类似于上面的分析。但可以方面的在进行提交之前与提交之后添加callback函数。

 

在实现中出现了一个问题是:如果用Struts2的JSON返回结果,上传完成以后,不会调用form插件success对应的callback函数,并自动弹出JSON信息的下载页面,使用记事本打开可以看到对应的JSON信息。


对于这个问题有两个解决办法:

1. 不使用JSON方法,将Struts2的结果类型换成redirect

2. 不使用JSON方法,将Struts2的结果类型换成plaintext,直接输出处理情况信息

 

其他的一些解决办法是:可以使用Flex相关的技术来实现,看了一下Google Doc的文件上传,就是使用flash来实现的。

plaintext可以直接将处理结果信息写到Response,不需要另外创建新的结果页面,最后我采用了这种办法。 具体如下:

代码情况如下:

JSP页面:uploadDoc.jsp

<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>上传文件</title>
<script src="../js/jquery.js" type="text/javascript"></script>
<script src="../js/jquery.form.js" type="text/javascript"></script>
	<script language="javascript">	
      $(document).ready(function(){
          var validateForm = function() {
	        	var fileName = $('#theFile').val();
	  			var m=parseInt(fileName.toString().lastIndexOf("."))+1;
	  		    var extVal=fileName.toString().substr(m);
	  			if(extVal!="doc") {
	  				alert('文件类型必须为Word文件!');
	  				return false;
	  			}
	  			$('#upMessage').html('文件上传中,请等待... ...');
	  			return true;	
        };

          var showResponse = function(data,status) { 
              $('#upMessage').fadeIn("fast",function(){
             	 
              });
     		return true;
           };
    	  var options={		
    	    	target : '#upMessage',	
  				url : 'AjaxUploadProductDoc!upload.action',
  				beforeSubmit: validateForm,
  				success : showResponse,
  				resetForm:true
  			};
    	  $('#upForm').ajaxForm(options);    	  
      });     
	</script>
</head>
<body>
	<form id="upForm" method="POST" enctype="multipart/form-data">
		上传文件:<input type="file" name="file" id="theFile"/>
		<br/>
		<input type="submit" value="提交" />
		<div id="upMessage" style="displan:hidden"></div>
	</form>
	</body>
</html>

 

后台Java类: AjaxUploadProductDocAction.java

package org.xtwh.product.action;

import org.apache.log4j.Logger;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Date;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;

import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;

/**
 * 处理上传DOC文件
 * @author user
 *
 */
public class AjaxUploadProductDocAction extends ActionSupport{
	/**
	 * Logger for this class
	 */
	private static final Logger logger = Logger
			.getLogger(AjaxUploadProductDocAction.class);

	
	private static final int BUFFER_SIZE = 16 * 1024;
	
	private File file;
	private String contentType;	//上传文件的MIME类型
	private String fileName;	//上传文件的文件名,该文件名不包括文件的后缀
		
	private boolean success;	//标识上传是否成功
	private static final String TEXT = "text";
	
//访问页面
	public String execute() {
		return INPUT;
	}

//上传文件
	public String upload() throws IOException {
		if(fileName == null || fileName.equals("")) {
			success = false;
			printMessage();
			return TEXT;
		}		
			
		if (file != null) {
			//保存文件					
			copy(file, docFile);
			
			//进行其他处理
		} 		
		success = true;
		message = "上传文件成功。";
		printMessage();
		return TEXT;
	}
	
/**
 * 判断上传文件夹中是否有同名文件
 * @return
 */
	private boolean hasSameFile() {
		
		return false;
	}
	
//输出信息到response
	private void printMessage() throws IOException {
		ActionContext ctx = ActionContext.getContext();
		HttpServletResponse response = (HttpServletResponse)ctx.get(ServletActionContext.HTTP_RESPONSE); 
		response.setContentType("text/plain;charset=utf-8");
		response.setHeader("Cache-Control", "no-cache");
		
		PrintWriter pw = null;
		try {
			StringBuffer sb = new StringBuffer();
			if(success) {
				sb.append("上传文件成功!");				
			}else {
				sb.append("上传文件失败");
			}
			
			pw = response.getWriter();
			pw.print(sb.toString());
			
		} catch (IOException e) {
			logger.error("输出 错误!");
			e.printStackTrace();
		} 
		finally {
			if(pw != null) {
				pw.close();
				pw = null;
			}
		}
	}

//copy file
	private static void copy(File src, File dst)  {
        try  {
           InputStream in = null ;
           OutputStream out = null ;
            try  {                
               in = new BufferedInputStream( new FileInputStream(src), BUFFER_SIZE);
               out = new BufferedOutputStream( new FileOutputStream(dst), BUFFER_SIZE);
                byte [] buffer = new byte [BUFFER_SIZE];
                while (in.read(buffer) > 0 )  {
                   out.write(buffer);
               } 
            } finally  {
                if ( null != in)  {
                   in.close();
               } 
                 if ( null != out)  {
                   out.close();
               } 
           } 
        } catch (Exception e)  {
           e.printStackTrace();
       } 
   } 
	
	

	public boolean isSuccess() {
		return success;
	}
	public void setFile(File file) {
		this.file = file;
	}
	public void setFileContentType(String contentType) {
		this.contentType = contentType;
	}
	public void setFileFileName(String fileName) {
		this.fileName = fileName;
	}


	
}

 配置文件:

<action name="AjaxUploadProductDoc" class="org.xtwh.product.action.AjaxUploadProductDocAction">
	<result name="input">/product/uploadDoc.jsp</result>
	<result name="xml" type="plaintext"></result>
</action>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值