LearnUploading Files with AJAX

Matt West
writes on February 26, 2014

The introduction of AJAX marked a huge leap forward in the history of the web. The ability to communicate with a web server without reloading the page has revolutionised how web applications are built. The primary technology that enables AJAX (XMLHttpRequests) has evolved significantly since the initial conception of dynamic websites.

A nice feature added to XMLHttpRequests in recent years is the ability to handle file uploads. Traditionally many developers have resorted to using technologies like Flash to upload files to a server. The problem with this approach is that the user needs to have a third-party browser plugin installed.

In this post you’ll learn how to upload files to a server using native JavaScript technologies. The example we’re going to use supports uploading multiple files in a single request. However, you can apply the same principles to single-file uploads too.

Lets get started!

Selecting Files to Upload

The first thing you need to do is set up your HTML form that will allow the user to select the file(s) that they wish to upload. To keep things simple lets use a standard <input> element with the file type.

<form id="file-form" action="handler.php" method="POST">
  <input type="file" id="file-select" name="photos[]" multiple/>
  <button type="submit" id="upload-button">Upload</button>
</form>

Notice that the <input> element includes the multiple attribute. This will allow the user to select multiple files from the file picker launched by the browser. If you don’t specify this attribute the user can only select one file.

Now that you’ve got your HTML form set up lets take a look at the JavaScript code that will handle the file upload.

Uploading Files to the Server

First of all you need to create three variables that hold references to the <form>, <input>, and <button> elements in your HTML markup.

var form = document.getElementById('file-form');
var fileSelect = document.getElementById('file-select');
var uploadButton = document.getElementById('upload-button');

Next you need to attach an event listener to the form’s onsubmit event.

form.onsubmit = function(event) {
  event.preventDefault();

  // Update button text.
  uploadButton.innerHTML = 'Uploading...';

  // The rest of the code will go here...
}

Inside the event listener you start by calling preventDefault() on the event object passed into the handler. This will prevent the browser from submitting the form, allowing us to handle the file upload using AJAX instead.

Next you update the innerHTML property on the uploadButton to Uploading.... This just provides a bit of feedback to the user so they know the files are uploading.

Your next job is to retrieve the FileList from the <input> element and store this in a variable. You can do this by accessing the files property.

// Get the selected files from the input.
var files = fileSelect.files;

You then create a new FormData object. This is used to construct the key/value pairs which form the data payload for the AJAX request.

// Create a new FormData object.
var formData = new FormData();

Your next job is to loop through each of the files in the files array and add them to the formData object you just created. You’ll also want to check that the user has selected the type of file you’re expecting.

// Loop through each of the selected files.
for (var i = 0; i < files.length; i++) {
  var file = files[i];

  // Check the file type.
  if (!file.type.match('image.*')) {
    continue;
  }

  // Add the file to the request.
  formData.append('photos[]', file, file.name);
}

Here you’re first fetching the current file from the files array and then checking to make sure it’s an image. The file’s type property will return the file type as a string. You can therefore use the JavaScript match() method to ensure that this string matches the desired type. If the file type does not match, you skip the file by calling continue.

You then use the append method on the formData object to add this file to the data payload.


The FormData.append() method is used to handle Files, Blobs, or Strings.

// Files
formData.append(name, file, filename);

// Blobs
formData.append(name, blob, filename);

// Strings
formData.append(name, value);    

The first parameter specifies the name of the data entry. This will form the key in the data payload. The second parameter specifies either a File, Blob, or String that will be used as the value for the data entry. When appending a File or Blob you can also specify a filename, but this isn’t required.


Next you need to set up the XMLHttpRequest that is responsible for communicating with the server. To do this you first need to create a new XMLHttpRequest object.

// Set up the request.
var xhr = new XMLHttpRequest();

You now need to create a new connection to the server. You do this using the open method. This method takes three parameters. The HTTP method, the url that will handle the request, and a boolean value that determines whether the request should be dealt with asynchronously.

// Open the connection.
xhr.open('POST', 'handler.php', true);

Next you need to set up an event listener that will be triggered when the onload event is fired. Examining the status property of the xhr object will tell you if the request completed successfully.

// Set up a handler for when the request finishes.
xhr.onload = function () {
  if (xhr.status === 200) {
    // File(s) uploaded.
    uploadButton.innerHTML = 'Upload';
  } else {
    alert('An error occurred!');
  }
};

All that’s left to do now is send the request. Pass the formData object to the send method which is available on the xhr object.

// Send the Data.
xhr.send(formData);

That’s everything you need to know to start uploading files using AJAX. Your server-side code will need to extract the files from the request and process them as desired.

Browser Support

Browser support for the technologies used in this post is generally good. Internet Explorer being the only exception. You will be okay with IE 10 and above, but earlier versions of IE didn’t include support for some of the XMLHttpRequest features covered in this post.

IE Firefox Chrome Safari Opera
10.0+ 4.0+ 7.0+ 5+ 12+

Summary

In this post you’ve learned how to upload files to a web server using native JavaScript technologies. The advancement in functionality of XMLHttpRequests has eliminated the need for developers to use third-party browser plugins to handle file uploads. This is good as native browser features are often faster and more secure than those provided by a plugin.

How do you plan to use AJAX file uploads in your projects? Share your thoughts in the comments below.

Further Reading

32 Responses to “Uploading Files with AJAX”

  1. With Edge in the mix now, be careful with how you append files. Apparently, using filename parameter in Edge is not supported at this time:
    https://developer.mozilla.org/en-US/docs/Web/API/FormData

  2. Written in easy-to-read language and explained the concept required, it would also be beneficial if you could have explained the method to fetch it from the server side.

  3. Awesome comprehensive guide, thank you very much!

  4. Dear Matt,

    Very interesting read. And quite excellently appropriate for my long term strategy of making use of standards that encourage lingua franca for Desktop, Web and Mobile Development. One of the objectives of reading this is to add image processing to the file upload. So for instance a customer were to upload a vehicle licence. The next stage of the file upload will be to pick up the Vehicle Number and other details. Tot this dimension may be interesting to you. Thanks!

    Nasser
    SoftWorld

  5. Could anybody show me how should I intercept the formeData from a c# webmethod?

    [WebMethod]
    public static bool UploadFile(????) {
    //??????
    return true;
    }

    I will apreciate if anybody help with this inssue… Thank you!

  6. Hi,
    Nice tutorial but the problem is that this example will not work in IE 9(–) or older versions of any major browser so its realy not a good production code example.
    Thanks for sharing anyway.

  7. Maurizio Romano on June 10, 2016 at 4:21 pm said:

    Hi. Your code works fine, although it needed some tweaking in order to fit my scenario (multiple Ajax connections handled with the callback function technique). What puzzles me is why we need the formData variable and the “append stuff” : couldn’t we just use the standard document.forms[“file-form”] directly (using the attribute NAME instead of ID)?

  8. Hi Matt,

    where can I find the handler.php file and where shall I add it? under /var/www/html/ ?
    Thanks in advance

  9. I’m using it, and with a little tweaking it works. I’m using it within a CodeIgniter 3 framework, so it required a little bit of tweaking. But it works, thanks!

  10. For PHP you can use $_FILES[‘photos’][‘tmp_name’], not $_POST

  11. hi,
    When I append a key value pair using formdata.append(“key”,”value”), I was not able get that value posted back to server. I use PHP, the value doesnt show in $_REQUEST/$_POST. But the files do come in $_FILES. is there anything that im missing?

  12. Hi, i’ve a problem with my code. When i pass formData to my php function in order to save my file (image) on database, i get an error:

    “Only strings, FileObjects and UploadedFileObjects can be imported”

    Have solution? This is my code:

    HTML:

    Aggiungi

    JAVASCRIPT is like your code.

  13. Where can i learn how to handle the data in my .php file?

  14. スーパーコピー時計専売店当店は海外安心と信頼のスーパーコピーブライトリング、代引き店です.正規品と同等品質のシャネル コピー代引き,品質が秀逸,値段が激安!ブライトリングコピー,代引きなどの商品や情報が満載!全商品写真は100%実物撮影です! お客様の満足度は業界No.1です!スーパーコピー時計,時計コピー ,ブランド時計コピー販売(n級品)店舗 ブランド腕時計(ロレックス,ブライトリング,タグホイヤー,オメガ,ガガミラノなど)の最新 情報やイベントを紹介する正規販売店と腕時計コピーの専門サイトです。当店はロレックスやパテックフィリップなどの新品スーパーコピー時計の販売と。
    ブランドコピー時計大人気を海外激安通販専門店ロレックス、ブルガリ、フランク ミュラー、シャネル、カルティエ、オメガ、IWC、ルイヴィトン、オーデマ ピゲ、ブライトリング、グッチ、エルメス、パネライ、パテックフィリップ偽物(コピー商品)のブランドの腕時計の販売、通販。 http://www.ooowatch.com/tokei/zenith/index.html

  15. スーパーコピーブランドショップ有名ブランド品の輸入業、卸売り業、インターネット小売販売N級,,S級 ヴィトン、シャネル、グッチ、財布、バッグ。 高級腕時計ROLEX 、OMEGA 、CARTIER 、 BVLGARI、是非ご覧下さい。2015超人気腕時計、LOUIS VUITTON新品の大量入荷!商品の数量は多い、品質はよい、価格は低い、現物写真!本当の意味でのハイレプがほしい方にお勧めです。経営方針: 品質を重視、納期も厳守、信用第一は当社の方針です。
    人気スーパーコピーブランド時計激安通販専門店私達は長年の実体商店の販売経験を持って、先進とプロの技術を持って、高品質のスーパーコピー時計づくりに 取り組んでいます。最高品質のロレックス時計コピー、カルティエ時計コピー、IWC時計コピー、ブライトリング時計コピー、パネライ時計コピー激安販売中商品の数量は多い、品質はよい。海外直営店直接買い付け!★ 2015年注文割引開催中,全部の商品割引10% ★ 在庫情報随時更新! ★ 実物写真、付属品を完備する。 ★ 100%を厳守する。 ★ 送料は無料です(日本全国)!★ お客さんたちも大好評です★ 経営方針: 品質を重視、納期も厳守、信用第一!税関の没収する商品は再度無料にして発送します http://www.ooowatch.com/tokei/vuitton/index.html

  16. BVLGARI(バッグ?財布?小物)CHLOE(バッグ?財布、小物)偽物ブランド,激安,コピー?ルイヴィトンバッグ,偽物?ルイヴィトン財布,コピーバッグ,ブランドバッグ,偽物バッグ,偽物シャネルバッグ,偽物エルメスバッグ,偽物グッチバッグ,偽物財布,コピー財布,時計の專門店
    業界最高峰のブランドコピー 激安、コピーブランド、スーパーコピーブランド(N級品)通販専門店!ブランドコピー,コピーブランド,スーパーコピーブランド,ブランドコピー 激安,偽物ブランド、偽物のバッグ、腕時計、財布など激安で買える!全部のスーパーコピー販売品物のなかで私達のブランド激安が一番有名です http://www.gowatchs.com/brand-237.html

  17. ブランドN級品ブランドコピー 代引き,スーパーコピー時計,ブランドN級品,楽天コピーブランド,,偽物ブラン日本最大級の最高のスーパーコピーブランド財布激安代引き販売店,スーパーコピー時計の激安老舗.!国内No.1時計コピー工房,アフターサービスも自ら製造したスーパーコピー時計なので、技術力でお客様に安心のサポー トをご提供させて頂きます。スーパーコピー 代引きN品をご 購入の方は、こちらへ.弊社は正規品と同等品質のコピー品を低価で お客様に提供します!すべての商品は品質2年無料保証です。
    2015ブランド財布コピールイヴィトン財布コピー,シャネル財布コピー,グッチ財布コピー,エルメス財布コピークロエ財布コピー,ブラダ財布コピー,ブルガリ財布コピー,ドルチェ&ガッバ―ナ財布コピーバレンシアガ財布コピー,ボッテガ.ヴェネタ財布コピーロレックス時計コピー,ブルガリ時計コピー,フランク ミュラー時計コピーシャネル時計コピー,カルティエ時計コピー_オメガ時計コピー,IWC時計コピールイヴィトン時計コピー,オーデマ ピゲ時計コピー,ブライトリング時計コピーコピーブランド、ブランド激安、人気ブランドの販売、通販、オークション、新作のスーパーコピーブランドコピー、韓国スーパーコピー、ブランド激安、偽物ブランド、ブランドバッグ、激安かばん、ルイヴィトン偽物、財布激安.商品は全く写真の通りです。 http://www.msnbrand.com/brand-copy-IP-5.html

  18. 日本スーパーコピーブランド時計販売店日本時計スーパーコピーを買うなら質屋がお得。ロレックススーパーコピー、ガガ?ミラノコピー、ブルガリ偽物、フランクミュラーレプリカ、
    ブランドコピーの専門店スーパーコピー豊富に揃えております、最も手頃ず価格だお気に入りの商品を購入。弊社フクショー(FUKUSHOW)ブランド腕時計、雑貨、小物最新作!エルメス バーキンスーパーコピー時計N品のみ取り扱っていまずのて、2年品質保証。エルメス食器,スーパーコピーブランド激安販売シャネル 財布スーパーコピー,スーパーコピーブランド 財布激安販売エルメス スーパーコピー,スーパーコピーブランド激安販売売スーパーコピーロレックス スーパーコピー,スーパーコピーROLEX激安販売IWC スーパーコピー,スーパーコピーIWC時計激安販売エルメス時計スーパーコピー,スーパーコピーhermes時計激安販売ボッテガ ヴェネタスーパーコピー,スーパーコピーブランド財布激安販売スーパーコピー時計スーパーコピーブランドバッグ時計コピー激安販売 http://www.wtobrand.com/he1.html

  19. Really nice tutorial.

    I’ve been using iframes all this while. I’m glad we can now use xhr to do uploads.

    Thanks for the tut.

  20. owais mushtaq on October 15, 2015 at 9:21 am said:

    Cleared my concepts helped a lot keep it up

  21. Thank you for another excellent post. Where else may anyone get that kind of information in such an ideal
    manner of writing? I’ve a presentation subsequent week, and I’m
    on the look for such info.

  22. Thanks Matt,
    I wrote similar tutorial, where I discussed cross-domain support too.
    http://zinoui.com/blog/cross-domain-ajax-upload

  23. Nicely written article Matt, clear and concise.
    I’ve spent a couple of days looking at Angular modules and other AJAX + JS offerings before discovering this, maybe it’s because of all that I was ready to be able to follow this, but I love the simplicity of this and the step by step explanations.
    For my needs I can live without compatibility to older browsers
    Thanks I found this to be great.

  24. Damian Skiedrzyński on September 10, 2015 at 10:09 am said:

    Ok but how to access the formData on the serveside?

  25. Thanks for your tut!
    Using native technologies is almost always better than third-party plug-ins! 😉

  26. Nice post. Would have been nice if you added a fall back method in case of older browsers…(hint hint I.E).

    • Here’s a workaround for old ie browsers.

      /**Check for xhr Object**/
      if (window.XMLHttpRequest) {
      xhr = new XMLHttpRequest();
      }
      else {
      /**Try using ActiveXObject for older ie versions..**/
      if (window.ActiveXObject) {
      try {
      xhr = new ActiveXObject(“Microsoft.XMLHTTP”);
      }
      catch (e) { }
      }
      }

      /**Now you can go ahead and use xhr*/
      if (xhr) {
      // Open the connection.
      xhr.open(‘POST’, ‘handler.php’, true);
      //Handle the onload event.
      xhr.onload = function () { /** */};
      // Send the Data.
      xhr.send(formData);
      }
      else {
      alert(“Sorry, but I couldn’t create an XMLHttpRequest”);
      }

      I hope you find this useful.
      Cheers..!!

  27. Is this the same method that it use for users to be able to upload file from a site? If you get what I mean Matt. Say am a user and go on to download a plugin say on wordpress or a theme. Is this the background action that goes on to make sure I get the right file?

    • Hi Kelvin,

      Some websites are certainly using this for things like uploading a user avatar.

      When downloading a file from a website, browsers often won’t open a new tab/window when you click a link to a file that it can’t display in the browser. Therefore it could look like the website is doing something nifty to make the download happen without refreshing the page but really it’s just the browser 🙂

  28. MOPDOBOPOT on March 2, 2014 at 2:34 am said:

    Thanks! 🙂

  29. Very interesting article, I will give it a shot. Thank you for your advice.

Leave a Reply

You must be logged in to post a comment.

Want to learn more about Javascript?

Learn how to use JavaScript to add interactivity to websites.

Learn more