118

Without using any forms whatsoever, can I just send a file/files from <input type="file"> to 'upload.php' using POST method using jQuery. The input tag is not inside any form tag. It stands individually. So I don't want to use jQuery plugins like 'ajaxForm' or 'ajaxSubmit'.

Huangism
  • 16,278
  • 7
  • 48
  • 74
Elo Peri
  • 1,183
  • 2
  • 8
  • 6
  • 2
    Arrr.... I wantsta say it should work in HTML 5. But yera gonna to be rife with platform compatibility issues an' browsers of older than a few years. What be the harm in creating a form, or dynamically generatin a form from the nethers? – Yitzhak Sep 30 '15 at 04:12

7 Answers7

113

You can use FormData to submit your data by a POST request. Here is a simple example:

var myFormData = new FormData();
myFormData.append('pictureFile', pictureInput.files[0]);

$.ajax({
  url: 'upload.php',
  type: 'POST',
  processData: false, // important
  contentType: false, // important
  dataType : 'json',
  data: myFormData
});

You don't have to use a form to make an ajax request, as long as you know your request setting (like url, method and parameters data).

AbdelHady
  • 9,334
  • 8
  • 56
  • 83
Omid Monshizadeh
  • 1,514
  • 1
  • 10
  • 12
  • IMHO this is the best solution, however another choice is to use an – John Smith Nov 12 '14 at 16:41
  • Yes, that's true. Old browsers do not support FormData and ajax to upload files and the solution if to use iframe as a fallback on those browsers. – Omid Monshizadeh Nov 12 '14 at 22:27
  • 8
    Don't forget to add `processData: false` and `contentType: false` to the settings object or else you will receive Uncaught TypeError: Illegal invocation – jsmiff Jan 26 '15 at 20:58
  • 2
    Dudes, you saved my life!! :D Thank you @monshi and @ jsmiff.(the SOF disallow multiple users in the same comment). – Silvio Delgado Mar 20 '15 at 08:20
  • 5
    what is pictureInput in this?? – SAUMYA Jul 09 '16 at 13:16
  • 1
    @developersaumya `pictureinput` is the file input DOM element. – Omid Monshizadeh Jul 10 '16 at 04:19
  • If you plan to use php to receive the request as in the example, see the answer of Hadiyal Rakesh to figure out how the content of FormData is retrieved. For experts, it is sent as a "multipart/form-data". – Arnaud Aug 15 '22 at 16:49
50

All answers here are still using the FormData API. It is like a "multipart/form-data" upload without a form. You can also upload the file directly as content inside the body of the POST request using xmlHttpRequest like this:

var xmlHttpRequest = new XMLHttpRequest();

var file = ...file handle...
var fileName = ...file name...
var target = ...target...
var mimeType = ...mime type...

xmlHttpRequest.open('POST', target, true);
xmlHttpRequest.setRequestHeader('Content-Type', mimeType);
xmlHttpRequest.setRequestHeader('Content-Disposition', 'attachment; filename="' + fileName + '"');
xmlHttpRequest.send(file);

Content-Type and Content-Disposition headers are used for explaining what we are sending (mime-type and file name).

I posted similar answer also here.

UPDATE (January 2023):

You can also use the Fetch API to upload a file directly as binary content (as also was suggested in the comments).

const file = ...file handle...
const fileName = ...file name...
const target = ...target...
const mimeType = ...mime type...

const promise = fetch(target, { 
  method: 'POST', 
  body: file, 
  headers: {
    'Content-Type': mimeType,
    'Content-Disposition': `attachment; filename="${fileName}"`,
  },
});

promise.then(
  (response) => { /*...do something with response*/ },
  (error) => { /*...handle error*/ },
);

See also a related question here: https://stackoverflow.com/a/48568899/1697459

Wilt
  • 41,477
  • 12
  • 152
  • 203
  • 1
    This is great answer. It is completely avoiding the usage of form data. I can add little more to the usage of xmlHttpRequest. An XMLHttpRequest allows for asynchronous operations to be performed, which don't block the client (UI page). While using an HTML form, the client(UI Page) is blocked while the operation is being performed. – Harry Mar 06 '19 at 17:04
  • 1
    What about `fetch()`? – Vitaly Zdanevich Apr 18 '20 at 00:23
  • 2
    @VitalyZdanevich not sure what you mean with that? – Wilt Apr 18 '20 at 07:19
  • @Harry, I am sure you are aware that AJAX, which most of the answers here use, also rely on xmlHttpRequest. And if you use FormData() instead of writing an actual form in HTML, you have no blocking. Cheers – Stephen Miller Jun 14 '21 at 07:51
  • The solution of `2023` is great but how about the backend? – ar2015 Jan 24 '23 at 01:52
  • 1
    @ar2015 Not sure what you mean exactly? But the backend doesn't care about whether you use option one or two. They are exactly the same from a backend point of view. Or do you generally mean how to support binary upload on a backend? – Wilt Jan 24 '23 at 11:59
  • some typos/mistakes in code: `'Content-Disposition',` should be replaced with `'Content-Disposition':` and a `},` line removed. whole statement should become `const promise = fetch(target, { method: 'POST', body: file, headers: { 'Content-Type': mimeType, 'Content-Disposition': \`attachment; filename="${fileName}"\` } });` – Alessandro Lendaro Mar 18 '23 at 02:55
  • 1
    @AlessandroLendaro Thanks for your comment, I updated the answer accordingly... – Wilt Mar 18 '23 at 21:26
18

Step 1: Create HTML Page where to place the HTML Code.

Step 2: In the HTML Code Page Bottom(footer)Create Javascript: and put Jquery Code in Script tag.

Step 3: Create PHP File and php code copy past. after Jquery Code in $.ajax Code url apply which one on your php file name.

JS

//$(document).on("change", "#avatar", function() {   // If you want to upload without a submit button 
$(document).on("click", "#upload", function() {
  var file_data = $("#avatar").prop("files")[0]; // Getting the properties of file from file field
  var form_data = new FormData(); // Creating object of FormData class
  form_data.append("file", file_data) // Appending parameter named file with properties of file_field to form_data
  form_data.append("user_id", 123) // Adding extra parameters to form_data
  $.ajax({
    url: "/upload_avatar", // Upload Script
    dataType: 'script',
    cache: false,
    contentType: false,
    processData: false,
    data: form_data, // Setting the data attribute of ajax with file_data
    type: 'post',
    success: function(data) {
      // Do something after Ajax completes 
    }
  });
});

HTML

<input id="avatar" type="file" name="avatar" />
<button id="upload" value="Upload" />

Php

print_r($_FILES);
print_r($_POST);
sijpkes
  • 168
  • 10
Hadiyal Rakesh
  • 239
  • 2
  • 7
14

Based on [this tutorial][1], here a very basic way to do that:

$('your_trigger_element_selector').on('click', function(){    
    var data = new FormData();
    data.append('input_file_name', $('your_file_input_selector').prop('files')[0]);
    // append other variables to data if you want: data.append('field_name_x', field_value_x);
    
    $.ajax({
        type: 'POST',               
        processData: false, // important
        contentType: false, // important
        data: data,
        url: your_ajax_path,
        dataType : 'json',  
        // in PHP you can call and process a file in the same way as if it was submitted in a form:
        // $_FILES['input_file_name']
        success: function(jsonData){
            ...
        }
        ...
    }); 
});

Don't forget to add proper error handling [1]: http://abandon.ie/notebook/simple-file-uploads-using-jquery-ajax

france1
  • 141
  • 2
  • 12
Blaine_
  • 306
  • 3
  • 11
3

Try this puglin simpleUpload, no need form

Html:

<input type="file" name="arquivo" id="simpleUpload" multiple >
<button type="button" id="enviar">Enviar</button>

Javascript:

$('#simpleUpload').simpleUpload({
  url: 'upload.php',
  trigger: '#enviar',
  success: function(data){
    alert('Envio com sucesso');

  }
});
2

Sorry for being that guy but AngularJS offers a simple and elegant solution.

Here is the code I use:

ngApp.controller('ngController', ['$upload',
function($upload) {

  $scope.Upload = function($files, index) {
    for (var i = 0; i < $files.length; i++) {
      var file = $files[i];
      $scope.upload = $upload.upload({
        file: file,
        url: '/File/Upload',
        data: {
          id: 1 //some data you want to send along with the file,
          name: 'ABC' //some data you want to send along with the file,
        },

      }).progress(function(evt) {

      }).success(function(data, status, headers, config) {
          alert('Upload done');
        }
      })
    .error(function(message) {
      alert('Upload failed');
    });
  }
};
}]);
.Hidden {
  display: none
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div data-ng-controller="ngController">
  <input type="button" value="Browse" onclick="$(this).next().click();" />
  <input type="file" ng-file-select="Upload($files, 1)" class="Hidden" />
</div>

On the server side I have an MVC controller with an action the saves the files uploaded found in the Request.Files collection and returning a JsonResult.

If you use AngularJS try this out, if you don't... sorry mate :-)

Tim Penner
  • 3,551
  • 21
  • 36
Shabi_669
  • 190
  • 4
2

A non-jquery (React) version:

JS:

function fileInputUpload(e){

    let formData = new FormData();
    formData.append(e.target.name, e.target.files[0]);

    let response = await fetch('/api/upload', {
      method: 'POST',
      body: formData
    });

    let result = await response.json();

    console.log(result.message);
}

HTML/JSX:

<input type='file' name='fileInput' onChange={(e) => this.fileInput(e)} />

You might not want to use onChange, but you can attach the uploading part to any another function.

Peter Utekal
  • 87
  • 10