Upload File with Ajax Xmlhttprequest

Upload file with Ajax XMLHttpRequest

  1. There is no such thing as xhr.file = file;; the file object is not supposed to be attached this way.
  2. xhr.send(file) doesn't send the file. You have to use the FormData object to wrap the file into a multipart/form-data post data object:

    var formData = new FormData();
    formData.append("thefile", file);
    xhr.send(formData);

After that, the file can be access in $_FILES['thefile'] (if you are using PHP).

Remember, MDC and Mozilla Hack demos are your best friends.

EDIT: The (2) above was incorrect. It does send the file, but it would send it as raw post data. That means you would have to parse it yourself on the server (and it's often not possible, depend on server configuration). Read how to get raw post data in PHP here.

AJAX File Upload with XMLHttpRequest

To avoid the post_max_size limitation problem... but also out of memory problems on both sides :

On the client side

  • use PUT instead of POST :

    xhr.open("put", "upload.php", true);

  • add custom headers to specify original FileName and FileSize :

    xhr.setRequestHeader("X-File-Name", file.name);
    xhr.setRequestHeader("X-File-Size", file.size);

  • use the File object directly in your XHR send method :

    xhr.send(file);

    Please note that the File object can be obtained directly via the “files” property of your input[type=file] DOM object

On the server side

  • read the custom headers via $_SERVER :

    $filename = $_SERVER['HTTP_X_FILE_NAME'];
    $filesize = $_SERVER['HTTP_X_FILE_SIZE'];

  • read file data using php://input :

    $in = fopen('php://input','r');

You'll then be able to send very big files (1GB or more) without any limitation!!!

This code works for FireFox 4+, Chrome 6+, IE10+

jQuery Ajax File Upload

File upload is not possible through AJAX.

You can upload file, without refreshing page by using IFrame.

You can check further details here.


UPDATE

With XHR2, File upload through AJAX is supported. E.g. through FormData object, but unfortunately it is not supported by all/old browsers.

FormData support starts from following desktop browsers versions.

  • IE 10+
  • Firefox 4.0+
  • Chrome 7+
  • Safari 5+
  • Opera 12+

For more detail, see MDN link.

javascript xhr file upload without jQuery

formData.append( ???, ??? ); // file

Yes, a file. There is an example in the MDN documentation:

formData.append('userpic', myFileInput.files[0], 'chris.jpg');
xhr.setRequestHeader('Content-type', 'multipart/form-data; charset=UTF-8');

Remove that. XHR will generate the correct content type for you. Doing it manually will fail to include the (essential) boundary information.

and second, if i want to send "formData" via XHR, do i just put "formData" variable into "xhr.send" method like this?

Yes.

How do I upload a file using FormData and XmlHTTPRequest?

I found two issues in your code:

  1. In JavaScript code, you explicitly defined the "Content-Type" as "multipart/form-data". JS automatically gets the content type when you make the XHR Request.
  2. In the 4th line of your PHP code, the key of the $_FILE is "file". You need to change it to "myfile", in order to make it work.

You can check my edited code below:

JS Code:

function uploadFile() {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState === XMLHttpRequest.DONE) {
if (xhr.status === 200) {
console.log('success');
} else {
console.log('error');
}
}
};
xhr.open('POST','php/parsefile.php',true);
var formData = new FormData();
formData.append("myfile", document.querySelector('#fileInput').files[0]);
xhr.send(formData);
}

PHP Code:

<?php
echo "Name: ". $_FILES['myfile']['name'];
echo "Error: ".$_FILES['myfile']['error'];

Ajax style upload equiv to XmlHttpRequest for file uploading to MVC controller? Uploading via ajax to MVC controller solved

Hopefully this will help someone else out there as I spent quite some time on this. Here is how to post a file via $.ajax WITHOUT any additional plugin, and WITHOUT an Ajax.BeginForm tag in the html view.

JAVASCRIPT

    $("button[id$='uploadfile']").click(function (evt) {
alert("upload file");
// relatively irrelevant name used here but is not what model binder uses in MVC
var file_data = $("#csvIdentifierFileBase").prop("files")[0]; // Getting the properties of file from file field
var form_data = new FormData(); // Creating object of FormData class
// THIS IS IMPORTANT, THE NAME HERE **"file"** IS WHAT THE MODEL BINDER USES IN MVC CONTROLLER
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: "alt/Import",
dataType: 'script',
cache: false,
contentType: false,
processData: false,
data: form_data, // Setting the data attribute of ajax with file_data
type: 'post'
});
});

HTML NO FORM TAGS NO PLUGGINS

         // name and id of input type file relatively irrelevant 
<div class="col-md-12">
<input type="file" name="csvIdentifierFileBase" id="csvIdentifierFileBase"/>
<button id="uploadfile" name="action" value="Import" >Import</button>
</div>

CONTROLLER

    [System.Web.Http.HttpPost]
public ActionResult Import(HttpPostedFileBase file) // THIS VAIRABLE NAME HAS TO BE THE SAME AS WHAT IS PASSED IN VIA THE SCRIPT FOR FORM DATA
{
HttpResponseMessage result = null;
HttpPostedFileBase file = Request.Files[0]; //Uploaded file JUST A SECOND WAY TO ACCESS THE SAME INFORMATION THAT IS COMING IN AS HttpPostedFileBase file
}

HOWEVER here's the GIT
FormData() is not supported in IE so this approach will not work for IE

Supporting information can be found here
http://blog.w3villa.com/websites/uploading-filesimage-with-ajax-jquery-without-submitting-a-form/

IE ALTERNATIVE TO ABOVE

HTML

        <div class="col-md-12">
<input type="file" name="csvIdentifierFileBase" id="csvIdentifierFileBase"/>
<button id="uploadfile" name="action" value="Import" >Import</button>
</div>

JAVASCRIPT

$("button[id$='uploadfile']").click(function (evt) {
evt.preventDefault();
var $newForm = $('<form>', {
'action': 'alt/Import',
'method': 'post',
'enctype': 'multipart/form-data',
'target':'_top'
//dynamically appending the input type file to the dynamically generated form and it MUST be appended to the page to work. "appendTo(body") submit then remove
}).append($("#csvIdentifierFileBase")).appendTo('body').submit().remove();

});

NOW THE NAME DOES MATTER

Since the input element is being dynamically added to the form the name does have to match the controller method param name for the model binder to work.

[System.Web.Http.HttpPost]
public ActionResult Import(HttpPostedFileBase csvIdentifierFileBase)
{

}

Fundamentally no different then having a form tag around the inputs which is the situation I'm trying to avoid. The reason I'm doing it this way and why I was trying to avoid multiple forms on a page was because I was in a situation where I would have had nested form tags which will not work.



Related Topics



Leave a reply



Submit