3073

jQueryで非同期にファイルをアップロードしたいと考えています。

$(document).ready(function () {
    $("#uploadbutton").click(function () {
        var filename = $("#file").val();

        $.ajax({
            type: "POST",
            url: "addFile.do",
            enctype: 'multipart/form-data',
            data: {
                file: filename
            },
            success: function () {
                alert("Data Uploaded: ");
            }
        });
    });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<span>File</span>
<input type="file" id="file" name="file" size="10"/>
<input id="uploadbutton" type="button" value="Upload"/>

ファイルがアップロードされる代わりに、ファイル名のみを取得しています。この問題を解決するにはどうすればよいですか?

4

34 に答える 34

2590

HTML5を使用すると、AjaxとjQueryを使用してファイルをアップロードできます。それだけでなく、ファイルの検証(名前、サイズ、およびMIMEタイプ)を実行したり、HTML5進行状況タグ(またはdiv)を使用して進行状況イベントを処理したりできます。最近、ファイルアップローダーを作成する必要がありましたが、 Flash 、Iframe、プラグインを使用したくありませんでした。調査の結果、解決策を思いつきました。

HTML:

<form enctype="multipart/form-data">
    <input name="file" type="file" />
    <input type="button" value="Upload" />
</form>
<progress></progress>

まず、必要に応じて検証を行うことができます。たとえば.on('change')、ファイルの場合:

$(':file').on('change', function () {
  var file = this.files[0];

  if (file.size > 1024) {
    alert('max upload size is 1k');
  }

  // Also see .name, .type
});

$.ajax()ボタンをクリックして送信します。

$(':button').on('click', function () {
  $.ajax({
    // Your server script to process the upload
    url: 'upload.php',
    type: 'POST',

    // Form data
    data: new FormData($('form')[0]),

    // Tell jQuery not to process data or worry about content-type
    // You *must* include these options!
    cache: false,
    contentType: false,
    processData: false,

    // Custom XMLHttpRequest
    xhr: function () {
      var myXhr = $.ajaxSettings.xhr();
      if (myXhr.upload) {
        // For handling the progress of the upload
        myXhr.upload.addEventListener('progress', function (e) {
          if (e.lengthComputable) {
            $('progress').attr({
              value: e.loaded,
              max: e.total,
            });
          }
        }, false);
      }
      return myXhr;
    }
  });
});

ご覧のとおり、HTML5(およびいくつかの調査)を使用すると、ファイルのアップロードが可能になるだけでなく、非常に簡単になります。例のHTML5コンポーネントの一部はすべてのブラウザで利用できるわけではないため、GoogleChromeで試してみてください。

于 2012-01-06T13:34:48.380 に答える
293

2019 年の更新:人口統計が使用しているブラウザーによって異なります。

file「新しい」HTML5 APIについて理解しておくべき重要なことは、それが IE 10 までサポートされていなかったということです。狙っている特定の市場で、古いバージョンの Windows を好む傾向が平均よりも高い場合は、その市場にアクセスできない可能性があります。

2017 年の時点で、ブラウザーの約 5% が IE 6、7、8、または 9 のいずれかです。大企業 (たとえば、これが B2B ツールまたはトレーニング用に提供するもの) に向かう場合、その数は急増する可能性があります。2016 年に、私はマシンの 60% 以上で IE8 を使用している会社と取引しました。

この編集の時点で2019年で、最初の回答からほぼ11年後です。IE9 以前は世界的に 1% マーク前後ですが、使用率が高いクラスターがまだあります。

これからの重要なポイントは、機能が何であれユーザーが使用しているブラウザーを確認することです。そうしないと、クライアントへの成果物で「自分に合っている」というだけでは不十分である理由について、すぐに、そして痛ましい教訓を学ぶことになります。caniuseは便利なツールですが、人口統計をどこから取得するかに注意してください。それらはあなたのものと一致しない場合があります。これは、エンタープライズ環境ほど真実ではありません。

2008年からの私の答えは次のとおりです。


ただし、実行可能なファイル アップロードの非 JS メソッドがあります。ページ上に iframe を作成し (CSS で非表示にする)、フォームを対象としてその iframe に投稿できます。メインページは移動する必要はありません。

これは「実際の」投稿であるため、完全にインタラクティブではありません。ステータスが必要な場合は、それを処理するサーバー側のものが必要です。これは、サーバーによって大きく異なります。ASP.NETには、より優れたメカニズムがあります。PHP プレーンは失敗しますが、Perlまたは Apache の変更を使用して回避できます。

複数のファイルをアップロードする必要がある場合は、ファイルを 1 つずつアップロードすることをお勧めします (最大ファイル アップロード制限を克服するため)。最初のフォームを iframe に投稿し、上記を使用して進行状況を監視し、完了したら 2 番目のフォームを iframe に投稿します。

または、Java/Flash ソリューションを使用します。彼らは自分の投稿でできることにおいてはるかに柔軟です...

于 2008-10-03T10:41:31.320 に答える
116

この目的には、 Fine Uploaderプラグインを使用することをお勧めします。あなたのJavaScriptコードは次のようになります。

$(document).ready(function() {
  $("#uploadbutton").jsupload({
    action: "addFile.do",
    onComplete: function(response){
      alert( "server response: " + response);
    }
  });
});
于 2008-11-21T16:38:06.750 に答える
105

注: この回答は古くなっています。XHR を使用してファイルをアップロードできるようになりました。


XMLHttpRequest (Ajax)を使用してファイルをアップロードすることはできません。iframe または Flash を使用して効果をシミュレートできます。iframe を介してファイルを投稿して効果を得る優れたjQuery フォーム プラグイン。

于 2008-10-03T10:36:38.677 に答える
103

将来の読者のためにまとめます。

非同期ファイルアップロード

HTML5で

FormDataFile APIがサポートされている場合 (どちらも HTML5 機能) 、メソッドを使用して jQuery でファイルをアップロードできます。$.ajax()

FormData を使用せずにファイルを送信することもできますが、どちらの方法でも、 XMLHttpRequest (Ajax)で送信できるようにファイルを処理するには、File API が存在する必要があります。

$.ajax({
  url: 'file/destination.html', 
  type: 'POST',
  data: new FormData($('#formWithFiles')[0]), // The form with the file inputs.
  processData: false,
  contentType: false                    // Using FormData, no need to process data.
}).done(function(){
  console.log("Success: Files sent!");
}).fail(function(){
  console.log("An error occurred, the files couldn't be sent!");
});

簡単で純粋な JavaScript ( jQuery なし) の例については、「FormData オブジェクトを使用してファイルを送信する」を参照してください。

後退する

HTML5 がサポートされていない ( File APIがない) 場合、他の純粋な JavaScript ソリューション ( Flashや他のブラウザー プラグインがない) は、 XMLHttpRequestオブジェクトを使用せずに非同期要求をエミュレートできる非表示の iframe手法だけです。

これは、ファイル入力を使用してフォームのターゲットとして iframe を設定することで構成されます。ユーザーがリクエストを送信すると、ファイルがアップロードされますが、メイン ページを再レンダリングする代わりに、iframe 内にレスポンスが表示されます。iframe を非表示にすると、プロセス全体がユーザーに対して透過的になり、非同期リクエストがエミュレートされます。

適切に実行すれば、事実上どのブラウザーでも動作するはずですが、iframe からの応答を取得する方法についていくつか注意点があります。

この場合、 iframe 技術を使用するBifröstのようなラッパー プラグインを使用することを好むかもしれませんが、次のようなメソッドだけでファイルを送信できるようにするjQuery Ajax トランスポートも提供します。$.ajax()

$.ajax({
  url: 'file/destination.html', 
  type: 'POST',
  // Set the transport to use (iframe means to use Bifröst)
  // and the expected data type (json in this case).
  dataType: 'iframe json',                                
  fileInputs: $('input[type="file"]'),  // The file inputs containing the files to send.
  data: { msg: 'Some extra data you might need.'}
}).done(function(){
  console.log("Success: Files sent!");
}).fail(function(){
  console.log("An error occurred, the files couldn't be sent!");
});

プラグイン

Bifröstは、jQuery の ajax メソッドにフォールバック サポートを追加する小さなラッパーにすぎませんが、jQuery フォーム プラグインjQuery ファイル アップロードなどの前述のプラグインの多くには、HTML5 からさまざまなフォールバックまでのスタック全体と、プロセスを容易にするいくつかの便利な機能が含まれています。ニーズと要件に応じて、裸の実装またはこのプラグインのいずれかを検討することをお勧めします。

于 2014-08-25T14:17:29.217 に答える
86

このAJAX ファイル アップロード jQuery プラグインは、何らかのファイルをアップロードし、応答をコールバックに渡します。

  • 特定の HTML には依存しません。<input type="file">
  • サーバーが特定の方法で応答する必要はありません
  • 使用するファイルの数や、ページ上のどこにあるかは問題ではありません

-- 最小限の使用 --

$('#one-specific-file').ajaxfileupload({
  'action': '/upload.php'
});

-- あるいは --

$('input[type="file"]').ajaxfileupload({
  'action': '/upload.php',
  'params': {
    'extra': 'info'
  },
  'onComplete': function(response) {
    console.log('custom handler for file:');
    alert(JSON.stringify(response));
  },
  'onStart': function() {
    if(weWantedTo) return false; // cancels upload
  },
  'onCancel': function() {
    console.log('no file selected');
  }
});
于 2011-07-29T00:34:20.920 に答える
63

以下のスクリプトを使用して、たまたま正常に機能する画像をアップロードしています。

HTML

<input id="file" type="file" name="file"/>
<div id="response"></div>

JavaScript

jQuery('document').ready(function(){
    var input = document.getElementById("file");
    var formdata = false;
    if (window.FormData) {
        formdata = new FormData();
    }
    input.addEventListener("change", function (evt) {
        var i = 0, len = this.files.length, img, reader, file;

        for ( ; i < len; i++ ) {
            file = this.files[i];

            if (!!file.type.match(/image.*/)) {
                if ( window.FileReader ) {
                    reader = new FileReader();
                    reader.onloadend = function (e) {
                        //showUploadedItem(e.target.result, file.fileName);
                    };
                    reader.readAsDataURL(file);
                }

                if (formdata) {
                    formdata.append("image", file);
                    formdata.append("extra",'extra-data');
                }

                if (formdata) {
                    jQuery('div#response').html('<br /><img src="ajax-loader.gif"/>');

                    jQuery.ajax({
                        url: "upload.php",
                        type: "POST",
                        data: formdata,
                        processData: false,
                        contentType: false,
                        success: function (res) {
                         jQuery('div#response').html("Successfully uploaded");
                        }
                    });
                }
            }
            else
            {
                alert('Not a vaild image!');
            }
        }

    }, false);
});

説明

response を使用divしてアップロード アニメーションとアップロード完了後の応答を表示します。

最良の部分は、このスクリプトを使用するときに、ファイルとともに id などの追加データを送信できることです。extra-dataスクリプトのように言及しました。

PHP レベルでは、これは通常のファイル アップロードとして機能します。エクストラデータはデータとして取得できます$_POST

ここでは、プラグインなどを使用していません。必要に応じてコードを変更できます。ここでやみくもにコーディングしているわけではありません。これは、あらゆる jQuery ファイル アップロードのコア機能です。実はジャバスクリプト。

于 2013-01-25T11:03:28.370 に答える
53

ごく簡単にバニラ JavaScript で実行できます。これが私の現在のプロジェクトのスニペットです:

var xhr = new XMLHttpRequest();
xhr.upload.onprogress = function(e) {
    var percent = (e.position/ e.totalSize);
    // Render a pretty progress bar
};
xhr.onreadystatechange = function(e) {
    if(this.readyState === 4) {
        // Handle file upload complete
    }
};
xhr.open('POST', '/upload', true);
xhr.setRequestHeader('X-FileName',file.name); // Pass the filename along
xhr.send(file);
于 2013-02-17T09:34:41.950 に答える
45

私が過去にこれを行った最も簡単で最も堅牢な方法は、非表示の iFrame タグをフォームでターゲットにするだけで、ページをリロードせずに iframe 内で送信されます。

これは、プラグイン、JavaScript、または HTML 以外の「魔法」を使用したくない場合です。もちろん、これを JavaScript と組み合わせることができます。

<form target="iframe" action="" method="post" enctype="multipart/form-data">
    <input name="file" type="file" />
    <input type="button" value="Upload" />
</form>

<iframe name="iframe" id="iframe" style="display:none" ></iframe>

onLoadサーバーエラーまたは成功応答の iframe の内容を読み取り、それをユーザーに出力することもできます。

Chrome、iFrame、および onLoad

-注-アップロード/ダウンロードを行うときにUIブロッカーをセットアップする方法に興味がある場合にのみ、読み続ける必要があります

現在、Chrome は、ファイルの転送に iframe が使用されている場合、iframe の onLoad イベントをトリガーしません。Firefox、IE、および Edge はすべて、ファイル転送の onload イベントを発生させます。

Chrome で機能することがわかった唯一の解決策は、Cookie を使用することでした。

基本的にアップロード/ダウンロードの開始時にそれを行うには:

  • [クライアント側] Cookie の存在を探す間隔を開始します
  • [サーバー側] ファイル データに対して必要なことは何でも行う
  • [サーバー側] クライアント側間隔の Cookie を設定する
  • [クライアント側] Interval は Cookie を見て、onLoad イベントのように使用します。たとえば、UI ブロッカーを開始してから onLoad (または Cookie が作成されたとき) に UI ブロッカーを削除できます。

これに Cookie を使用するのは見苦しいですが、機能します。

ダウンロード時に Chrome でこの問題を処理するための jQuery プラグインを作成しました。

https://github.com/ArtisticPhoenix/jQuery-Plugins/blob/master/iDownloader.js

アップロードにも同じ基本原理が適用されます。

ダウンローダーを使用するには(明らかにJSを含めます)

 $('body').iDownloader({
     "onComplete" : function(){
          $('#uiBlocker').css('display', 'none'); //hide ui blocker on complete
     }
 });

 $('somebuttion').click( function(){
      $('#uiBlocker').css('display', 'block'); //block the UI
      $('body').iDownloader('download', 'htttp://example.com/location/of/download');
 });

サーバー側では、ファイルデータを転送する直前に、Cookie を作成します。

 setcookie('iDownloader', true, time() + 30, "/");

プラグインは Cookie を確認し、onCompleteコールバックをトリガーします。

于 2014-06-26T04:43:12.280 に答える
33

これは Rails 環境で書き上げました。軽量の jQuery フォーム プラグインを使用する場合、JavaScript はわずか 5 行です。

remote_form_for課題は、標準がマルチパートフォームの送信を理解していないため、AJAX アップロードを機能させることです。RailsがAJAXリクエストでシークバックするファイルデータを送信するつもりはありません。

ここで、jQuery フォーム プラグインの出番です。

Rails のコードは次のとおりです。

<% remote_form_for(:image_form, 
                   :url => { :controller => "blogs", :action => :create_asset }, 
                   :html => { :method => :post, 
                              :id => 'uploadForm', :multipart => true }) 
                                                                        do |f| %>
 Upload a file: <%= f.file_field :uploaded_data %>
<% end %>

関連する JavaScript は次のとおりです。

$('#uploadForm input').change(function(){
 $(this).parent().ajaxSubmit({
  beforeSubmit: function(a,f,o) {
   o.dataType = 'json';
  },
  complete: function(XMLHttpRequest, textStatus) {
   // XMLHttpRequest.responseText will contain the URL of the uploaded image.
   // Put it in an image element you create, or do with it what you will.
   // For example, if you have an image elemtn with id "my_image", then
   //  $('#my_image').attr('src', XMLHttpRequest.responseText);
   // Will set that image tag to display the uploaded image.
  },
 });
});

そして、これが Rails コントローラーのアクションです。

 @image = Image.new(params[:image_form])
 @image.save
 render :text => @image.public_filename

過去数週間、Bloggity でこれを使用してきましたが、チャンピオンのように機能しています。

于 2009-08-13T22:44:39.223 に答える
33

シンプルな Ajax アップローダーも別のオプションです。

https://github.com/LPology/Simple-Ajax-Uploader

  • クロスブラウザ -- IE7+、Firefox、Chrome、Safari、Opera で動作
  • HTML5 以外のブラウザでも複数の同時アップロードをサポート
  • Flash や外部 CSS は不要 -- 5Kb の Javascript ファイルが 1 つだけ
  • オプションの、完全なクロスブラウザー プログレス バーの組み込みサポート (PHP の APC 拡張機能を使用)
  • 柔軟で高度にカスタマイズ可能 -- 任意の要素をアップロード ボタンとして使用し、独自の進行状況インジケーターをスタイルします
  • フォームは不要です。アップロード ボタンとして機能する要素を提供するだけです
  • MIT ライセンス -- 商用プロジェクトで無料で使用可能

使用例:

var uploader = new ss.SimpleUpload({
    button: $('#uploadBtn'), // upload button
    url: '/uploadhandler', // URL of server-side upload handler
    name: 'userfile', // parameter name of the uploaded file
    onSubmit: function() {
        this.setProgressBar( $('#progressBar') ); // designate elem as our progress bar
    },
    onComplete: function(file, response) {
        // do whatever after upload is finished
    }
});
于 2013-06-26T01:12:21.447 に答える
32

私が見つけた解決策は、<form>ターゲットを非表示の iFrame にすることでした。その後、iFrame は JS を実行して、(ページの読み込み時に) 完了したことをユーザーに表示できます。

于 2008-10-18T19:30:50.720 に答える
26

jQuery Uploadifyは、以前にファイルをアップロードするために使用したもう 1 つの優れたプラグインです。JavaScript コードは次のように単純です。ただし、新しいバージョンは Internet Explorer では機能しません。

$('#file_upload').uploadify({
    'swf': '/public/js/uploadify.swf',
    'uploader': '/Upload.ashx?formGuid=' + $('#formGuid').val(),
    'cancelImg': '/public/images/uploadify-cancel.png',
    'multi': true,
    'onQueueComplete': function (queueData) {
        // ...
    },
    'onUploadStart': function (file) {
        // ...
    }
});

私は多くの検索を行い、プラグインを使用せずに ajax のみを使用してファイルをアップロードする別のソリューションにたどり着きました。解決策は次のとおりです。

$(document).ready(function () {
    $('#btn_Upload').live('click', AjaxFileUpload);
});

function AjaxFileUpload() {
    var fileInput = document.getElementById("#Uploader");
    var file = fileInput.files[0];
    var fd = new FormData();
    fd.append("files", file);
    var xhr = new XMLHttpRequest();
    xhr.open("POST", 'Uploader.ashx');
    xhr.onreadystatechange = function () {
        if (xhr.readyState == 4) {
             alert('success');
        }
        else if (uploadResult == 'success')
            alert('error');
    };
    xhr.send(fd);
}
于 2013-06-16T09:49:29.407 に答える
11

ここでは、フォーム ファイルをプレビューしてサーバーに送信できる動作デモを使用して、解決済みのソリューションを確認できます。あなたの場合、サーバーへのファイルのアップロードを容易にするためにAjaxを使用する必要があります。

<from action="" id="formContent" method="post" enctype="multipart/form-data">
    <span>File</span>
    <input type="file" id="file" name="file" size="10"/>
    <input id="uploadbutton" type="button" value="Upload"/>
</form>

送信されるデータはフォームデータです。jQuery では、ボタン クリックの代わりにフォーム送信機能を使用して、以下に示すようにフォーム ファイルを送信します。

$(document).ready(function () {
   $("#formContent").submit(function(e){

     e.preventDefault();
     var formdata = new FormData(this);

 $.ajax({
     url: "ajax_upload_image.php",
     type: "POST",
     data: formdata,
     mimeTypes:"multipart/form-data",
     contentType: false,
     cache: false,
     processData: false,
     success: function(){

     alert("successfully submitted");

     });
   });
});

詳細を見る

于 2016-07-19T05:18:34.047 に答える
8

ここで、ファイルのアップロード プロセスの非同期処理を探します: https://developer.mozilla.org/en-US/docs/Using_files_from_web_applications

リンクからのサンプル

<?php
if (isset($_FILES['myFile'])) {
    // Example:
    move_uploaded_file($_FILES['myFile']['tmp_name'], "uploads/" . $_FILES['myFile']['name']);
    exit;
}
?><!DOCTYPE html>
<html>
<head>
    <title>dnd binary upload</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <script type="text/javascript">
        function sendFile(file) {
            var uri = "/index.php";
            var xhr = new XMLHttpRequest();
            var fd = new FormData();

            xhr.open("POST", uri, true);
            xhr.onreadystatechange = function() {
                if (xhr.readyState == 4 && xhr.status == 200) {
                    // Handle response.
                    alert(xhr.responseText); // handle response.
                }
            };
            fd.append('myFile', file);
            // Initiate a multipart/form-data upload
            xhr.send(fd);
        }

        window.onload = function() {
            var dropzone = document.getElementById("dropzone");
            dropzone.ondragover = dropzone.ondragenter = function(event) {
                event.stopPropagation();
                event.preventDefault();
            }

            dropzone.ondrop = function(event) {
                event.stopPropagation();
                event.preventDefault();

                var filesArray = event.dataTransfer.files;
                for (var i=0; i<filesArray.length; i++) {
                    sendFile(filesArray[i]);
                }
            }
        }
    </script>
</head>
<body>
    <div>
        <div id="dropzone" style="margin:30px; width:500px; height:300px; border:1px dotted grey;">Drag & drop your file here...</div>
    </div>
</body>
</html>
于 2015-07-08T17:59:34.517 に答える
2

どの ajax を約束し、ファイルが有効でバックエンドに適切に保存されているかを確認すると、ユーザーがページをナビゲートしているときにアニメーションを前に使用できるようになります。

再帰的なアプローチで並列アップロードまたはスタッキングすることもできます

于 2020-02-28T15:06:49.697 に答える