web-dev-qa-db-ja.com

jqueryファイルのアップロード-IE done callback data.result issue

jQueryファイルを使用しています アップロードプラグイン

UI部分は使用せず、基本的な部分のみを使用します。

次のことをすると、IEに問題が発生します。

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

IE on data.resultObjectIE9少なくとも、他の人にはわからない...)

Chrome/Firefoxは、応答Text(サーバーからの単純なプレーンテキスト)です。

アイデア?

30
CLod

私はちょうど同じ問題に遭遇しましたが、XHRファイルのアップロードがIE(偶数9))でサポートされていないという事実によるものだと思います。 :

Safari 5以降、Firefox 4以降、およびChromeはXHRファイルのアップロードをサポートしているため、fileuploadプラグインはファイルを完全に非同期に転送でき、サーバーからの純粋なテキスト応答が可能です。 doneイベントハンドラーのdata.resultを介して利用でき、簡単に使用できます。

ただし、IEでは、非表示のiframeでページ全体を更新することでファイル転送が行われ、doneハンドラーのdata.resultが応答テキスト付きの完全なdocumentオブジェクトになります<html><body><iframe><pre>タグの奥深くにラップされます。

これにより、IEでデータにアクセスするのが面倒になるだけでなく、ブラウザ間でデータにアクセスする方法が異なります。

私の解決策:

forceIframeTransportオプションをtrueに設定します。これにより、すべてのブラウザーがIEなどの非表示のiframeでファイルを転送します。 XHRファイルのアップロードを見逃すのは残念ですが、少なくともこれはすべてのブラウザで同じ種類の応答を提供します。次に、doneハンドラーで、documentオブジェクトから次のように結果を抽出しました。

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

あなたの場合、コードは次のようになります。

$('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 );
    }
...

ここで重要なのは、サーバーからの応答のコンテンツタイプが「text/plain」であることです。お気づきかもしれませんが、IEはjson応答を保存または開くようにユーザーに求めることがあります。

問題を解決するときに役立つことがわかったリンクを次に示します。 https://github.com/blueimp/jQuery-File-Upload/wiki/Browser-support (下部の「XMLHttpRequest」セクションを参照) https://github.com/blueimp/jQuery-File-Upload/wiki/Options (1/3ほど下の「forceIframeTransport」を参照)

これがお役に立てば幸いです!

50
Justin

上記と同様の問題があり、応答タイプをapplication/jsonからtext/plainこれらの問題を修正しました。

13
Unknown

実際、これはjquery.iframe-transport.jsは次のとおりです(基本バージョンには、このプラグインが追加のリファレンスとして含まれています)。必要なのは、dataTypeプロパティをjsonに設定し、jquery.iframe-transportプラグインはiframeの結果を自動的に解析するため、doneハンドラーで同じロジックを使用できます。

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

私はこの同じ問題に出くわしました。 IE 9はdoneコールバックをトリガーしませんが、wouldalwaysコールバックをトリガーします。トリッキーな部分はJSON応答を抽出していました引数からのオブジェクト(ドキュメントの主張にもかかわらず、jquery.iframe-transport.jsを含める必要があることはわかりませんでした。)

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...
  }
}
4
Joey

ここでの回答は、問題を理解して解決するのに非常に役立ちました。私は、最新のブラウザがXmlHttpRequestを使用してアップロードし、IE9がiframeを使用できるようにする(ハッカーのある場合は満足のいくソリューションになりました)(IE7/8ではテストしませんでした):

  • 使用する jquery.iframe-transport.js、iframeからの応答の抽出を処理します。ページに含めるだけで、fileuploadプラグインが使用します。
  • ファイルのアップロードに使用されるサーバーアクションで、JSONの結果を返しますが、content-type に設定 "text/plain"、IEファイルを開くようにユーザーに促すプロンプトを避けるために
  • Doneコールバックで、JSONテキストを手動で評価します
  • 最後に、評価された結果オブジェクトを以前のように使用します

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...
        }
    }
}
1
Pierre Henry

私の問題、理由は:クロスドメインです。

つまり、IE8/9では、サーバーのURLはjsファイルと同じドメインの下にある必要があります。 jquery.iframe-transport.jsはiframeに基づいており、クロスドメインはできません。チェック hehe

JQuery.file-upload.jsがブラウザ自体を判断するため、forceIframeTransportをtrueに設定する必要はありません。

サーバーはContent-Type:text/htmlまたはtext/plainを返す必要があり、jsはdataType: 'json'を使用できますが、問題ありません。少なくとも、私のものです。

デバッグするときに、try/catchブロックであるline85付近でjquery.iframe-transport.jsにブレークポイントを設定できます。そこで壊れる場合は、iframeが使用されていることを意味し、応答を取得できます。現時点では、DOM(iframe内)でjsonを見ることができますが、クロスドメイン化すると、未定義の応答が返されます。

私のコード。特別なし:

$('.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();
    }
});
0
NoteCode

これについてのすばらしい説明をしてくれた@Justinに感謝します。 「pre」要素に対するクエリの作成を避け、代わりに@EnsignRickyのコメントのような単純なソリューションを作成します。

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