[js]jQueryのajaxで画像(ファイル)アップロードをする


以前作成した画像アップロードAPIを使うサンプルを作ろうと思い、jQueryを使ってajaxで画像アップロードをやってみました。

  • layout
# app/views/layouts/application.html.erb

!DOCTYPE html>
<html>
<head>
  <title>UploadApi</title>
  <%= stylesheet_link_tag    'application', media: 'all' %>
  <%= csrf_meta_tags %>
</head>
<body>
  <%= yield %>
  <script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
  <script src="/js/upload.js" type="text/javascript"></script>
</body>
</html>
  • 画像アップロードフォーム
# app/views/user/index.html.erb

<form class='update'>
  name: <input type="text" name="name" required /><br />
  image: <input type="file" name="profile" accept="image/jpeg,image/png" required /><br />
  <input type="submit" value="upload" />
</form>

<div id="profile">
  <p>アップロードした画像が表示されます</p>
</div>
  • アップロードjs
# public/js/upload.js

(function(win, doc) {

  "use strict";

  $('form').submit(function(e) {
    e.preventDefault();

    var fd = new FormData($(this)[0]);
    // 個別にパラメータ指定する場合は以下のようにする
    //var fd = new FormData();
    //fd.append('name', $(this).find(':text[name="name"]').val());
    //fd.append('profile', $(this).find(':file[name="profile"]')[0].files[0]);

    $.ajax('/api/user/update', {
      method: "POST",
      processData: false,
      contentType: false,
      data: fd,
      dataType: 'json',
      success: function(json) {
        var img = $('<img>').attr('src', json.profile_url);
        $('#profile').append(img);
        $('form').find(':submit').attr('disabled', true);
      },
      error: function(json) {
        alert('エラーが発生しました');
      }
    });
  });

})(this, document);

最初、ajaxのdata部分に

{ profile: $(this).find(':file[name="profile"]').val() }

という風に書いていたのですが、それだとファイル名になってしまいうまくアップロードできないことが判明。

ファイルを送る場合はFormDataオブジェクトにformの内容を格納して送信するのが良いそうです。

また、processDatafalseにしてクエリ文字列への変換を無効化し、contentTypeもFormDataオブジェクトが決めてくれるのでfalseにしています。

これで簡単な画像アップロードができるようになりました。

参考