`

处理Extjs4 文件上传时若服务器出错带来的问题

阅读更多
一个典型的Extjs4上传文件表单:

Ext.define('org.allenz.UploadFormPanel', {
	extend : 'Ext.form.Panel',

	initComponent : function() {
		var states = Ext.create('Ext.data.Store', {
			fields : [ 'name', 'value' ],
			data : [ {
				name : '成功',
				value : 0
			}, {
				name : '失败',
				value : 1
			}, {
				name : '模拟服务器错误',
				value : 2
			} ]
		});

		var me = this;
		Ext.apply(me, {
			width : 300,
			height : 100,
			items : [ {
				xtype : 'filefield',
				fieldLabel : '上传文件',
				name : 'upload',
				buttonText : '浏览',
				allowBlank : false
			}, {
				xtype : 'combo',
				fieldLabel : '上传结果',
				name : 'state',
				allowBlank : false,
				store : states,
				displayField : 'name',
				valueField : 'value'
			} ],
			dockedItems : [ {
				xtype : 'toolbar',
				dock : 'bottom',
				ui : 'footer',
				items : [ '->', {
					text : '上传',
					scope : me,
					handler : me.onUpload
				} ]
			} ]
		});
		me.callParent(arguments);
	},

	onUpload : function() {
		var me = this;
		var form = me.getForm();
		if (!form.isValid()) {
			return;
		}
		// 浏览器提示
		Ext.Msg.show({
			msg : '正在上传...',
			width : 300,
			closable : false
		});
		form.submit({
			url : 'upload.do',
			scope : me,
			success : me.uploadSuccess,
			failure : me.uploadFailure
		});
	},

	uploadSuccess : function(form, action) {
		Ext.Msg.hide();
		Ext.Msg.alert('提示', '上传成功!');
	},

	uploadFailure : function(form, action) {
		Ext.Msg.hide();
		var errorText;
		switch (action.failureType) {
		case Ext.form.action.Action.CLIENT_INVALID:
			// 浏览器检查失败
			errorText = '请选择上传文件!';
			break;
		case Ext.form.action.Action.SERVER_INVALID:
			// 服务器检查文件失败
			errorText = action.result.errors[0].message;
			break;
		default:
			// 网络或服务器错误
			errorText = '因网络或服务器错误,上传失败!';
		}
		Ext.Msg.alert('错误', errorText);
	}
});


服务器端代码(基于Java Spring,只起返回作用不真正处理文件):
@Controller
public class UploadTestController {

	@RequestMapping("/upload.do")
	void upload(HttpServletResponse response, int state) throws IOException {
		String result = null;
		switch (state) {
		case 0:
			result = "{success:true}";
			break;
		case 1:
			result = "{success:false,errors:[{message:'文件格式错误!'}]}";
			break;
		case 2:
			throw new RuntimeException("抛出异常");
		}
		response.setContentType("text/html");
		response.setCharacterEncoding("UTF-8");
		response.resetBuffer();
		PrintWriter out = response.getWriter();
		out.write(result);
		out.close();
	}
}

这里约定,服务器应返回的JSON字符串格式如下:
{success:boolean,errors:[{message:string}]}

在下拉框里选择“成功”或“失败”,上传文件后浏览器都能弹出对话框并显示信息,但是当选择'模拟服务器错误'后上传,浏览器并没有如我们预想那样提示“因网络或服务器错误,上传失败!”,而是在“正在上传...”提示中卡死,控制台提示“uncaught exception: You're trying to decode an invalid JSON String: ...”为什么会这样呢?

其实Ajax只能够收发基于文本的数据,是不能够处理二进制数据的。之所以看上去能够“异步上传”,是因为Extjs针对包含上传的表单使用了iframe提交的方法,流程如下:

1.在页面创建一个iframe和隐藏的form,form的各字段和Extjs表单字段相同;
2.将form的target指向该iframe,并监听iframe的onload事件;
3.提交这个form,待iframe的onload事件触发后(加载完成),读取iframe的innerHtml,并保存到responseText;
4.默认情况下,尝试将responseText进行JSON解码;
5.根据解码结果,调用success或failure回调。

隐患在第3步已经产生,因为不是使用Ajax提交,Extjs无法获取Http状态码,只能假定iframe返回的是JSON数据。而服务器出错时,返回的一般是Html错误页面,Extjs尝试对Html内容进行JSON解码最后抛出异常。

有没有办法处理这种情况呢?答案是有的。负责表单提交的Ext.form.Basic有一个参数errorReader,指定了errorReader时,解释responseText的责任就落到该数据读取器身上。在该数据读取器中先对responseText进行JSON解码测试,若发生异常,制造一个失败JSON对象。代码如下:

// 定义错误信息数据模型
Ext.define('org.allenz.ErrorModel', {
	extend : 'Ext.data.Model',

	fields : [ 'message' ]
});
// 定义上传错误数据读取器
Ext.define('org.allenz.UploadErrorReader', {
	extend : 'Ext.data.reader.Json',
	alternateClassName : 'Ext.data.UploadErrorReader',
	alias : 'reader.upload',

	// 设置错误信息根节点为errors
	root : 'errors',

	// 覆盖getResponseData
	getResponseData : function(response) {
		var data;
		try {
			// 尝试将responseText解码为JSON
			data = Ext.decode(response.responseText);
		} catch (ex) {
			// 不能解码,则服务器没有正常返回,制造一个包含错误信息的JSON对象
			// 最终这个data会被Reader转换为
			// result = {success : false, errors : [yourErrorModel]}
			// 从在回调函数中action.result读取
			data = {
				success : false,
				total : 1,
				errors : [ {
					message : '因网络或服务器错误,上传失败!'
				} ]
			};
		}

		return data;
	}
});


在Extjs表单类的initComponent函数末尾(执行this.callParent(arguments);后)加入:
var form = this.getForm();
		var errorReader = Ext.create('org.allenz.UploadErrorReader', {
			model : 'ErrorModel'
		});
		Ext.apply(form, {
			errorReader : errorReader
		});


注意返回数据格式要改为Reader能够辨认的格式,如{success:boolean,total:integer,errors:[yourErrorModel,...]}
  • 大小: 3.9 KB
分享到:
评论
2 楼 xiaoyaozjl 2012-10-14  
王伟康 写道
文件上传成功,但还是报错, You're trying to decode an invalid JSON String:    这个问题怎样修改


上传处理完毕后,要主动在服务器端返回(在response中写入)Extjs4能处理的json才行,比如"{success:true}"
1 楼 王伟康 2012-09-12  
文件上传成功,但还是报错, You're trying to decode an invalid JSON String:    这个问题怎样修改

相关推荐

    ExtJS4多文件上传,带进度条及管理

    ExtJS4提供了一种解决方案,允许用户通过一个交互式的界面来上传多个文件,并可以分别处理每个文件的上传状态。 **三、上传组件:uploadPanel** 在ExtJS4中,可以使用自定义组件或者第三方插件来实现文件上传功能。...

    EXTJS 多文件上传

    4. **错误处理**:如果某个文件上传失败,`MultiFileUploadField` 可以提供相应的错误提示,帮助用户理解问题所在并采取相应措施。 5. **自定义上传策略**:开发人员可以设置上传策略,例如限制文件类型、大小,...

    extjs 多文件上传

    在ExtJS中实现多文件上传功能,能够极大地提升用户体验,特别是在处理大量数据或文件时。本篇文章将详细探讨如何使用ExtJS实现多文件上传,并涵盖相关的关键知识点。 一、ExtJS 文件上传组件 在ExtJS中,我们可以...

    Extjs4文件上传,后台struts2

    在本文中,我们将深入探讨如何使用ExtJS 4与Struts2框架实现文件上传功能。ExtJS是一个强大的JavaScript库,提供了丰富的用户界面组件,而Struts2是Java Web开发中的一个MVC框架,用于处理后端业务逻辑。下面,我们...

    extjs多文件上传

    在IT行业中,多文件上传是Web应用中常见的一项功能,特别是在需要用户批量上传图片、文档等数据时。本文将深入探讨“extjs多文件上传”这一主题,结合标签“源码”和“工具”,我们将主要关注如何使用ExtJS库实现这...

    extjs4 文件上传

    4. **上传事件**:文件上传组件触发一系列事件,如`change`事件(当用户选择文件时触发),`beforeupload`事件(在文件上传前触发,可用于预处理或验证),以及`uploadcomplete`事件(文件上传成功后触发)。...

    ExtJS 多文件上传 UploadDialog For ExtJS3.x

    - **AJAX请求**:通过Ajax发送异步请求到服务器端,处理文件上传过程中的各种逻辑。 - **事件监听**:监听文件选择事件、上传开始/结束事件等,以便实时更新UI状态。 **3. 事件队列(EventQueue)的设计** `Ext.ux....

    批量上传文件 EXTJS文件上传 上传组件

    在EXTJS中,实现批量上传文件是一项常见的需求,尤其在处理大量数据或媒体文件时。EXTJS的文件上传组件提供了方便的方式来处理这些任务,允许用户一次性选择多个文件进行上传,极大地提高了工作效率。 批量上传文件...

    extjs 4.2 多文件上传

    用Ext编写的多文件上传组件,已封装。 支持多文件上传,文件下载,文件删除,

    ExtJS验证上传文件类型

    例如,我们只想让用户上传特定的文件类型,例如txt文件,那么如何实现当用户上传非txt文件时,给出错误提示呢?这篇文章将详细讲述ExtJS如何验证文件上传类型。 使用 Validator 验证文件类型 在 ExtJS 中,我们...

    Extjs多文件上传

    4. **服务器端处理**:在服务器端,你需要处理这些上传的文件,例如保存到指定位置,验证文件类型和大小等。这将取决于你使用的语言和框架,例如在Java中可能是使用JSP,而在PHP中可能是使用`$_FILES`全局变量。 5....

    ExtJS原生多文件拖动上传组件

    ExtJS原生多文件拖动上传组件 使用时修改包路径 1.多文件上传 2.支持拖动上传 3.支持图片压缩 4.支持图片合并 5.文件排序 可扩展实时图片预览 api //初始化画板 initCanvas //上传文件窗口 uploadWindow //初始化...

    ExtJS4 上传文件类型和大小的判断方法(实例)

    对应的描述看本人博文《ExtJS4 上传文件类型和大小的判断方法(实例) 》:http://blog.csdn.net/biboheart/article/details/10579175 在这里不具体描述了。看题也大概可以知道这些代码实现了什么应用。

    extjs 多文件上传控件

    7. **服务器端处理**: 虽然ExtJS负责前端的文件选取和发送,但实际的文件存储和处理发生在服务器端。服务器端需要能够接收并处理多文件上传的请求,比如PHP的`$_FILES`全局变量或者Node.js的Multer库。 8. **跨域...

    EXTJS3.0多文件上传组件

    4. **文件上传安全**:在实现多文件上传时,要考虑到文件大小限制、文件类型检查、防止跨站脚本攻击(XSS)和跨站请求伪造(CSRF)等安全问题。 5. **用户体验优化**:设计良好的用户界面和交互,如进度条展示、...

    Extjs4 swfupload 多文件上传

    在本文中,我们将深入探讨如何在ExtJS4框架中整合SWFUpload库,实现多文件上传功能。ExtJS4是一个强大的JavaScript组件库,用于构建富客户端应用,而SWFUpload则是一个流行的选择,用于在浏览器中实现文件上传,特别...

    Extjs4后台框架、多文件上传

    文件上传功能在Web应用中是非常常见的需求,尤其在处理大量数据或者用户需要提交多个文件时。在ExtJS4中,实现多文件上传通常会涉及以下知识点: 1. **Ext.form.FileField**:这是ExtJS4中的一个组件,用于创建文件...

    Structs2+ExtJs多文件上传,多选文件加入列表

    总的来说,结合Structs2的后端处理能力和ExtJS的前端交互,可以创建一个功能完善的多文件上传系统。用户可以方便地选取多个文件,看到清晰的上传进度和速度,同时具备取消上传的能力。这种方案提高了用户的交互体验...

    extjs java 上传文件进度条

    总结来说,"extjs java 上传文件进度条"这个主题涉及到前端与后端的交互,需要理解ExtJS组件的使用,熟悉Ajax异步上传,掌握Java服务器处理文件上传的逻辑,以及HTTP协议、JSON通信等相关知识。通过这些技术的结合,...

Global site tag (gtag.js) - Google Analytics