jquery 文件上传 - IE 完成回调 data.result 问题

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8814068/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 11:05:41  来源:igfitidea点击:

jquery file upload - IE done callback data.result issue

jqueryinternet-explorerpluginsfile-upload

提问by CLod

I'm using jQueryfile upload plugin.

我正在使用jQuery文件上传插件

I don't use the UIpart, only basic one.

我不使用UI零件,只使用基本零件。

When I do the following, I'm having an issue in IE:

当我执行以下操作时,我遇到了问题IE

$('input#fileupload').fileupload({
    url: '/upload',
    done: function (e, data) {
    if(data.result != null && $.trim(data.result) != '')
        $('a#attachment').html(data.result);
    }
    //......................

on IEthe data.resultis an Object(IE9at least, not sure the others...)

IEdata.resultObjectIE9至少,不知道其他人......)

On Chrome/Firefoxis just the response Text(simple plain text from the server).

On Chrome/Firefox只是响应Text(来自服务器的简单纯文本)。

Ideas?

想法?

回答by Justin

I just ran into the same problem, and I think it is due to the fact that XHR file uploads are not supported in IE (even 9). Here's what I believe is happening, and my solution:

我刚刚遇到了同样的问题,我认为这是因为 IE(甚至 9)不支持 XHR 文件上传。这是我认为正在发生的事情,以及我的解决方案:

Since Safari 5+, Firefox 4+, and Chrome support XHR file uploads, the fileupload plugin can transfer the files truly asynchronously, allowing for a pure text response from the server. This pure text response is available via data.resultin the doneevent handler, and can be used easily.

由于 Safari 5+、Firefox 4+ 和 Chrome 支持 XHR 文件上传,fileupload 插件可以真正异步传输文件,允许来自服务器的纯文本响应。这个纯文本响应是经由提供data.resultdone事件处理程序,并且可以容易地使用。

In IE, however, the file transfer occurs via a full page refresh in a hidden iframe, causing data.resultin the donehandler to be a full documentobject, with the response text wrapped deep inside <html><body><iframe><pre>tags.

在IE中,然而,文件传输通过一个隐藏的iframe刷新整个页面出现,导致data.resultdone处理程序是一个完整的document对象,具有响应文本包裹内心深处<html><body><iframe><pre>的标签。

Not only does this make it a pain to get to the data in IE, it makes the way you get to the data different between browsers.

这不仅使在 IE 中获取数据变得痛苦,而且使您获取数据的方式因浏览器而异。

My solution:

我的解决方案:

I set the forceIframeTransportoption to true, which makes all browsers transfer files with a hidden iframe, like IE. It's unfortunate to miss out on XHR file uploads, but this at least gives us the same kind of response in all browsers. Then, in my donehandler, I extracted the result from the documentobject like so:

我将该forceIframeTransport选项设置为 true,这使得所有浏览器都使用隐藏的 iframe 传输文件,例如 IE。很遗憾错过 XHR 文件上传,但这至少在所有浏览器中为我们提供了相同的响应。然后,在我的done处理程序中,我从document对象中提取结果,如下所示:

var result = $( 'pre', data.result ).text();

In your case, I think the code would look something like this:

在你的情况下,我认为代码看起来像这样:

$('input#fileupload').fileupload({
    forceIframeTransport: true,
    url: '/upload',
    done: function ( e, data ) {
     var result = $( 'pre', data.result ).text();
     if( result != null && $.trim( result ) != '' )
        $( 'a#attachment' ).html( result );
    }
...

Also important to note here is that the Content Type of the response from my server is 'text/plain'. As you may have noticed, IE sometimes prompts the user to save or open a json response.

这里还需要注意的是,来自我的服务器的响应的内容类型是“文本/纯文本”。您可能已经注意到,IE 有时会提示用户保存或打开 json 响应。

Here are a couple links that proved useful when resolving the problem: https://github.com/blueimp/jQuery-File-Upload/wiki/Browser-support(see 'XMLHttpRequest' section at bottom) https://github.com/blueimp/jQuery-File-Upload/wiki/Options(see 'forceIframeTransport' about 1/3 of the way down)

以下是解决问题时证明有用的几个链接:https: //github.com/blueimp/jQuery-File-Upload/wiki/Browser-support(请参阅底部的“XMLHttpRequest”部分) https://github.com /blueimp/jQuery-File-Upload/wiki/Options(请参阅向下约 1/3 处的“forceIframeTransport”)

Hopefully this helps!

希望这会有所帮助!

回答by Unknown

I had problems similar to the ones mentioned above and found that changing the response type from application/jsonto text/plainfixed those issues.

我遇到了与上面提到的问题类似的问题,发现将响应类型从更改application/jsontext/plain修复了这些问题。

回答by Krisna Dharma

Actually this is what the jquery.iframe-transport.jsis for (the basic version also include this plugin as additional reference). What you need is to set the dataTypeproperty to jsonand the jquery.iframe-transportplugin will automatically parse the iframeresult, so you can have the same logic in your done handler.

实际上这就是jquery.iframe-transport.js它的用途(基本版本也包括这个插件作为额外的参考)。您需要的是将dataType属性设置为jsonjquery.iframe-transport插件将自动解析iframe结果,因此您可以在 done 处理程序中使用相同的逻辑。

$('#fileupload').fileupload({
...
    dataType: 'json'
...
});

回答by Joey

I ran into this same issue. IE 9 would not trigger the donecallback, but wouldtrigger the alwayscallback. The tricky part was extracting the JSON response object from the arguments. (Despite what the documentation claimed, I did not find that I needed to include jquery.iframe-transport.js.)

我遇到了同样的问题。IE 9 不会触发done回调,但触发always回调。棘手的部分是从参数中提取 JSON 响应对象。(尽管文档声称,我没有发现我需要包含 jquery.iframe-transport.js。)

My implementation of the alwayscallback looked something like this:

我的always回调实现看起来像这样:

always: function(e, data) {
  var result;
  if (data.textStatus == 'parsererror') {  // IE9 fails on upload's JSON response
    result = JSON.parse(data.jqXHR.responseText);
  } else if (data.textStatus == 'success') {
    result = data.result;
  }

  if (result) {
    // ...perform custom handling...
  }
}

回答by Pierre Henry

The answers here were very useful to understand and solve the problem. I ended up with a satisfactory if hacky solution, that allows modern browsers to upload using XmlHttpRequest, and IE9 to use iframe(didn't test with IE7/8) :

这里的答案对于理解和解决问题非常有用。我最终得到了一个令人满意的解决方案,它允许现代浏览器使用XmlHttpRequest和 IE9上传iframe(未使用 IE7/8 进行测试):

  • Use jquery.iframe-transport.js, it will take care of extracting the response from the iframe. Just include it in the page, the fileuploadplugin will use it.
  • On the server action used to upload the files, return a JSON result, but with content-typeset to "text/plain", in order to avoid IE prompting the user to open the file
  • In the done callback, manually evalutate the JSON text
  • Finally, use the evaluated result object as before
  • 使用jquery.iframe-transport.js,它将负责从 iframe 中提取响应。只需将它包含在页面中,fileupload插件就会使用它。
  • 在用于上传文件的服务器动作上,返回一个 JSON 结果,但content-type设置为"text/plain",以避免 IE 提示用户打开文件
  • 在 done 回调中,手动评估 JSON 文本
  • 最后,像以前一样使用评估结果对象

Here is the JS code :

这是JS代码:

//file upload
var upload = $(fileUploadElmtId).fileupload({

    dataType: 'text',  //if we use JSON IE9 will ask the user to open the file... see the FileUploadController class
    url: uploadUrl,
    autoUpload: true,

    done: function (e, data) {


        //parse the JSON string that was received from the server - since it was received as text/plain it is not automatically evaluated
        var result = $.parseJSON(data.result);

        $.each(result.files, function (index, file) {
            //do something with the result - in my case it is an array of uploaded files...
        }
    }
}

回答by NoteCode

My problem, the reason is: Cross-Domain.

我的问题,原因是:跨域。

That is to say: in IE8/9, your server url should under the same domain as your js file. For jquery.iframe-transport.js is based on iframe, in which you can not cross-domain. Check hehe

也就是说:在 IE8/9 中,你的服务器 url 应该和你的 js 文件在同一个域下。因为 jquery.iframe-transport.js 是基于 iframe 的,不能跨域。检查 嘿嘿

You need not set the forceIframeTransport to true, for jquery.file-upload.js will judge the browser itself.

您不需要将 forceIframeTransport 设置为 true,因为 jquery.file-upload.js 会判断浏览器本身。

Your server should return Content-Type: text/html, or maybe text/plain, and your js could use dataType: 'json', no problem. At least, mine is.

你的服务器应该返回 Content-Type: text/html,或者 text/plain,你的 js 可以使用 dataType: 'json',没问题。至少,我的是。

When you debug, you could set breakpoint in jquery.iframe-transport.js at about line85, the try/catch block. If it can break there, that means iframe used, and you could get the response. At this time, you could see your json in the DOM(in iframe), but if you cross-domained, you would got response as undefined.

调试时,您可以在 jquery.iframe-transport.js 中大约 line85(try/catch 块)处设置断点。如果它可以在那里中断,则意味着使用了 iframe,并且您可以获得响应。此时,您可以在 DOM(在 iframe 中)中看到您的 json,但是如果您跨域,您将得到未定义的响应。

My code. No special:

我的代码。没有特别:

$('.input-upload').fileupload({
    url: url, 
    dataType: 'json',
    autoUpload: false,
    acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i,
    maxFileSize: 999000,
    previewMaxWidth: 114,
    previewMaxHeight: 70,
    previewThumbnail: false,
    xhrFields: {
        withCredentials: true
    }
}).on('fileuploadadd', function (e, data) {
    $.each(data.files, function (index, file) {
        data.submit().success(function (json, textStatus, jqXHR) {
            // on success
        }).error(function (jqXHR, textStatus, errorThrown) {
            // on error
        });
    });
}).on('fileuploadprocessalways', function (e, data) {
    var _this = this;
    var file = data.files[data.index];
    if (file.preview) {
        // 显示图片预览
        var preview = $(this).parent().siblings('.preview');
        preview.append(file.preview).removeHide();
    }
});

回答by Grantzau

Thanks to @Justin for a great explanation on this. I would avoid making queries for the "pre" element and instead make a simple solution like commented by @EnsignRicky

感谢@Justin 对此进行了很好的解释。我会避免对“pre”元素进行查询,而是创建一个简单的解决方案,如@EnsignRicky 所评论的

done: function (e, data) {
  var result = data.result[0].body ? data.result[0].body.innerHTML : data.result
}

回答by Nazariy

I believe issue can be in server response, you can make sure that server always send correct heading by using following code:

我相信问题可能出在服务器响应中,您可以使用以下代码确保服务器始终发送正确的标题:

header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . "GMT");
header("Cache-Control: no-cache, must-revalidate");
header("Pragma: no-cache");
header("Content-type: text/x-json");
echo json_encode($array);
exit(0);