昨天做项目的时候,利用Extjs4+springmvc文件上传,服务器端springmvc处理上传文件很顺利,只是当springmvc返回json数据给extjs时却产生了奇怪的异常:
Uncaught Ext.JSON.decode(): You're trying to decode an invalid JSON String:......
google了大半天,原来是extjs文件上传时对服务器端返回数据的处理问题:
File uploads are not performed using normal 'Ajax' techniques, that is they are not performed using XMLHttpRequests. Instead a hidden <form>
element containing all the fields is created temporarily and submitted with its target set to refer to a dynamically generated, hidden <iframe>
which is inserted into the document but removed after the return data has been gathered.
The server response is parsed by the browser to create the document for the IFRAME. If the server is using JSON to send the return object, then theContent-Type header must be set to "text/html" in order to tell the browser to insert the text unchanged into the document body.
关键在于红色字体部分,对于文件上传,服务器端返回json对象时,则Content-Type必须为“text/html”
其实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回调。
如此则只须修改springmvc的response的ContentType即可
首先想到的是这样:
@RequestMapping(value="/uploadPhoto",method=RequestMethod.POST)
public @ResponseBody
ExtjsResultBean uploadPhoto(UploadFileBean uploadFile,
BindingResult bindingResult, HttpServletRequest request,HttpServletResponse response){
response.setContentType("text/html");
}
好像这样不行,extjs接收的服务器端返回的还是"application/json",
幸好在stackoverflow上一兄弟说这样能解决:
在spring-mvc.xml中:
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="com.wanghaisheng.bean.MyStringHttpMessageConverter"/>
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" >
<property name="supportedMediaTypes">
<array>
<value>text/html</value>*******
<value>application/json</value>
</array>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
spring controller中:
@RequestMapping(value="/uploadPhoto",method=RequestMethod.POST,produces = MediaType.TEXT_HTML_VALUE)
public @ResponseBody
ExtjsResultBean uploadPhoto(UploadFileBean uploadFile,
BindingResult bindingResult, HttpServletRequest request,HttpServletResponse response){}
则顺利解决