Reputation: 231
I'm working on a project where I'm trying to allow for a user to upload an xlsx file (not preview) for processing by dragging it into a box. I want it to work something like smallpdf's does. I've got the ability to get the filename from the user along with what I think is a binary string using this group of files:
if(window.FileReader) {
var drop;
addEventHandler(window, 'load', function() {
var status = document.getElementById('status');
drop = document.getElementById('drop');
var list = document.getElementById('list');
function cancel(e) {
if (e.preventDefault) { e.preventDefault(); }
return false;
}
// Tells the browser that we *can* drop on this target
addEventHandler(drop, 'dragover', cancel);
addEventHandler(drop, 'dragenter', cancel);
addEventHandler(drop, 'drop', function (e) {
e = e || window.event; // get window.event if e argument missing (in IE)
if (e.preventDefault) { e.preventDefault(); } // stops the browser from redirecting off to the image.
var dt = e.dataTransfer;
var files = dt.files;
for (var i=0; i<files.length; i++) {
var file = files[i];
var reader = new FileReader();
//attach event handlers here...
reader.readAsDataURL(file);
addEventHandler(reader, 'loadend', function(e, file) {
var bin = this.result;
var newFile = document.createElement('div');
newFile.innerHTML = 'Loaded : '+file.name+' size '+file.size+' B';
list.appendChild(newFile);
var fileNumber = list.getElementsByTagName('div').length;
status.innerHTML = fileNumber < files.length
? 'Loaded 100% of file '+fileNumber+' of '+files.length+'...'
: 'Done loading. processed '+fileNumber+' files.';
var img = document.createElement("img");
img.file = file;
img.src = bin;
list.appendChild(img);
}.bindToEventHandler(file));
}
return false;
});
Function.prototype.bindToEventHandler = function bindToEventHandler() {
var handler = this;
var boundParameters = Array.prototype.slice.call(arguments);
//create closure
return function(e) {
e = e || window.event; // get window.event if e argument missing (in IE)
boundParameters.unshift(e);
handler.apply(this, boundParameters);
}
};
});
} else {
document.getElementById('status').innerHTML = 'Your browser does not support the HTML5 FileReader.';
}
function addEventHandler(obj, evt, handler) {
if(obj.addEventListener) {
// W3C method
obj.addEventListener(evt, handler, false);
} else if(obj.attachEvent) {
// IE method.
obj.attachEvent('on'+evt, handler);
} else {
// Old school method.
obj['on'+evt] = handler;
}
}
Also, the HTML within the body of my webpage is written up as shown below.
<div id="file-container">
<div id="status">Drag the files from a folder to the selection area below ...</div>
<div id="drop">Drop Spreadsheet here</div>
<div id="list"></div>
</div><!--eod #file-container-->
As you can see, I'm not actually using a form. Do I absolutely have to use a form to send a file to PHP? If yes, are there other options?
I just am not sure how to transfer the file from my JavaScript code to my actual PHP to process the file. Any help would be appreciated. I've done a ton of research, to no avail. If you think another way of doing this would be better, I'm open to suggestions.
Upvotes: 0
Views: 127
Reputation: 36
I'm the developer of smallpdf. We upload the files directly in the request body, without multipart/form-data. There is also no need to use the FileReader API. XMLHttpRequests send method accepts a File/Blob etc as argument.
A simplified version of our upload looks like this:
function upload(file) {
var req = new XMLHttpRequest();
req.addEventListener('load', function () {
console.log(req.statusCode, req.responseText);
}.bind(this));
req.upload.addEventListener('progress', function (ev) {
console.log('progress', ev.loaded / file.size * 100);
}.bind(this));
req.upload.addEventListener('error', errorHandler);
req.addEventListener('error', errorHandler);
req.open('POST', '/upload/url', true);
req.setRequestHeader('Content-Type', file.type);
// Posts the file in the request body
req.send(file);
}
function errorHandler(error) {
console.log(error)
}
You can use something like this to get droped files or use the files of an input field.
var dropElement = document.body;
function cancel(ev) {
ev.preventDefault();
}
// cancel dragover event
dropElement.addEventListener('dragover', cancel);
// listen for drop events
dropElement.addEventListener('drop', function (ev) {
cancel(ev);
var files = [].slice.call(ev.dataTransfer.files);
files.forEach(upload);
});
Upvotes: 2
Reputation: 1584
Try doing something like this after you have read the file:
var fileContents = new FormData();
fileContents.append('file', bin);
$.ajax({
url : "processFile.php",
type: 'POST',
data: fileContents,
contentType: false,
processData: false,
success: function(data) {
alert("File sent sucessfully");
},
error: function() {
alert("Something went wrong");
}
});
Upvotes: 0