如何解决“文件上传返回JSON数据,在IE下提示下载文件”的问题?

黄勇 发布于 2013/08/29 15:01
阅读 64K+
收藏 5

UploadServlet.java

@WebServlet("/upload.do")
@MultipartConfig
public class UploadServlet extends HttpServlet {
    @Override
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 获取文件路径
        String filePath = WebUtil.getFilePath(request, "files");

        // 获取文件名
        Part part = request.getPart("file");
        String fileName = WebUtil.getFileName(request, part);

        // 写入文件
        part.write(filePath + "/" + fileName);

        // 返回结果
        Map<String, Object> data = new HashMap<String, Object>();
        data.put("fileName", fileName);
        data.put("fileType", part.getContentType());
        data.put("fileSize", part.getSize());
        WebUtil.writeJson(response, data);
    }
}


upload.html

<form id="login_form" action="/upload.do" method="post" enctype="multipart/form-data">
    <p>
        <label for="file">File:</label>
        <input type="file" id="file" name="file"/>
    </p>
    <p>
        <button type="submit">Upload</button>
    </p>
</form>
<div id="console"></div>


upload.js

$(function() {
    $('#login_form').ajaxForm({
        beforeSubmit: function() {
            if ($('#file').val() == '') {
                alert('Please choose a file!');
                return false;
            }
        },
        success: function(json) {
            if (json) {
                var html = '';
                html += '<p>File Name: ' + json.fileName + '</p>';
                html += '<p>File Type: ' + json.fileType + '</p>';
                html += '<p>File Size: ' + json.fileSize + '</p>';
                $('#console').html(html);
            }
        }
    });
});


问题

在Chrome、Firefox上运行正常,在IE8+中运行时,提示下载,如下图:


加载中
2
tix
tix
'Content-Type:text/html; charset=utf-8'

alanzyy
alanzyy
回复 @黄勇 : JSON.parse()在IE9下也不支持,在$.ajax中添加dataType:"json",能够自动解析json
黄勇
黄勇
刚刚发现,IE10可以支持application/json格式的Response了,也就是说低于IE10版本一下的IE浏览器都需要使用text/html格式的Response。
黄勇
黄勇
在Response头中指定Content-Type为text/html,而并非text/html,是可以解决问题的。这样返回给客户端的是一个JSON字符串(并非JSON对象),无需IE来解析。随后,使用JSON.parse()函数将JSON字符串解析为JSON对象即可。非常感谢你的回答! 但客户端JS代码有些不够优雅,能否通过统一的方式来设置呢?
0
走位风骚闪着腰
走位风骚闪着腰
ajaxForm不是jQuery自带的吧,是一种表单插件?
黄勇
黄勇
由于jQuery的Ajax函数很难实现文件上传功能,所以我选择了一款比较流行的jQuery插件--jQuery Form。官网:http://www.malsup.com/jquery/form/#getting-started
0
走位风骚闪着腰
走位风骚闪着腰

百度了下,应该是没加dataType:

dataType

期望返回的数据类型。null、“xml”、“script”或者“json”其中之一。dataType提供一种方法,它规定了怎样处理服务器的响应。这个被直接地反映到jQuery.httpData方法中去。下面的值被支持:

'xml':如果dataType == 'xml',将把服务器响应作为XML来对待。同时,如果“success”回调方法被指定, 将传回responseXML值。

'json':如果dataType == 'json', 服务器响应将被求值,并传递到“success”回调方法,如果它被指定的话。

'script':如果dataType == 'script', 服务器响应将求值成纯文本。

默认值:null(服务器返回responseText值)

黄勇
黄勇
就算在ajaxForm中指定了dataType为json,还是解决不了此问题,在IE下仍然出现下载提示框。下载后发现就是从服务端返回的JSON数据,这说明IE并没有对JSON数据进行解析。
走位风骚闪着腰
走位风骚闪着腰
回复 @鉴客 : 只要有助于解决问题就可取,转载不注明出处,有大环境的原因。
鉴客
鉴客
回复 @天朝子民鸭梨大 : 不要发这个垃圾网站的链接,所有文章都是转别人的,而且不注明出处!
走位风骚闪着腰
走位风骚闪着腰
http://www.open-open.com/lib/view/open1325032463827.html
0
戴威
戴威
response.setContentType("application/json;charset=UTF-8");

戴威
戴威
回复 @黄勇 : 关键是application/json
黄勇
黄勇
指定了charset=UTF-8也不能解决问题,这好像并非是字符集的问题。
0
黄勇
黄勇

我研究过jQuery Form插件的官网,有关文件上传的问题,作者是这样描述的。

To account for the challenges of script and JSON responses when using the iframe mode, the Form Plugin allows these responses to be embedded in a textarea element and it is recommended that you do so for these response types when used in conjuction with file uploads and older browsers.
地址: http://www.malsup.com/jquery/form/#file-upload

他用一个<textarea>HTML标签来封装需要返回的JSON数据,我个人认为此方案不够优雅,倒不如直接返回JSON字符串(text/html格式),然后再通过JSON.parse()解析为JSON对象来得痛快。大家认为呢?

0
黄勇
黄勇

最后,还是用代码来说明一下此问题是如何解决的吧。

Upload.java

@WebServlet("/upload.do")
@MultipartConfig
public class UploadServlet extends HttpServlet {
    @Override
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 获取文件路径
        String filePath = WebUtil.getFilePath(request, "files");

        // 获取文件名
        Part part = request.getPart("file");
        String fileName = WebUtil.getFileName(request, part);

        // 写入文件
        part.write(filePath + "/" + fileName);

        // 返回结果
        Map<String, Object> data = new HashMap<String, Object>();
        data.put("fileName", fileName);
        data.put("fileType", part.getContentType());
        data.put("fileSize", part.getSize());
//        WebUtil.writeJson(response, data);
        WebUtil.writeHtml(response, data); // 返回text/html格式的数据
    }
}
upload.js
$(function() {
    $('#login_form').ajaxForm({
        beforeSubmit: function() {
            if ($('#file').val() == '') {
                alert('Please choose a file!');
                return false;
            }
        },
        success: function(json) {
            json = JSON.parse(json); // 将JSON字符串解析为JSON对象
            if (json) {
                var html = '';
                html += '<p>File Name: ' + json.fileName + '</p>';
                html += '<p>File Type: ' + json.fileType + '</p>';
                html += '<p>File Size: ' + json.fileSize + '</p>';
                $('#console').html(html);
            }
        }
    });
});
返回顶部
顶部