My JavaScript book is out! Don't miss the opportunity to upgrade your beginner or average dev skills.
Showing posts with label upload. Show all posts
Showing posts with label upload. Show all posts

Friday, March 20, 2009

noSWFUpload - Zero Plug-In Multiple Upload

As announced a couple of days ago, I am finally proud to introduce my last library free Multiple Upload Component, now compatible with every browser and always without usage of 3rd parts plug-ins.


This little project has been hosted in Google Code and I promise I'll write there a complete documentation asap. Righ now, you can read the project source code via zip to understand what he little API is doing.

Update I added a couple of sections in the Wiki page ;)

Compatibility?
  • Internet Explorer 5.5 (probably 5 too), 6, 7, and 8
  • FireFox? 3 or greater
  • Google Chrome 1.0
  • Opera 8, 9, and 10
  • Safari 4 (current beta)
  • other browsers via unobtrusive iframe


Try the demo if you do not believe it :P

Sunday, March 15, 2009

Multiple Upload With Progress: Every Browser No Flash !!!

Update: released official version in Google Code, cross browser, and easy to use. blog enry


Ok guys, this is a quick and dirty entry in my blog. I need to write documentation, create the project in Google Code, explain better what I have done and how it works.
I do not want to give you the zip right now because I have to change name (silly me do not check before) and to do last tests ... but basically, what I have created this week end, is a graceful enhanced multiple file upload manager compatible with Chrome, FireFox, Internet Explorer (5.5 or greater), Opera, Safari.



The manager wrap an input type file and manages it allowing multiple files selection, where supported, or one after one insert with possibility to remove one or more file from the list.

Everything is absolutely customizable, since the wrapper is entirely in CSS, the library has a language namespace for errors or messages, and events are created by developers.

In those browsers were Ajax upload is not supported, the progress bar is simulated, but there is the feeling that something is happening.

In FireFox, where Ajax upload is supported, the progress is still simulated but at least the size, sent or total, is real.

Stay tuned for the official announcement, enjoy the demo in my website.

Quick thanks and credit to Silk Icon Set from famfamfam!

P.S. Yes, there is a file type filter as well, Flash like, and I have solved server side $_FILES problem with Safari 4 ... but please wait next blog entry!

Monday, March 09, 2009

Safari 4 Multiple Upload With Progress Bar

Update - I slightly modified the demo page adding another bar, the one for the current file. I'll update the zip asap but all you need is a copy and paste of the JS in the index. Apparently multiple should be set as multiple, rather than true ... in any ... it works as long as it is an attribute.


This one from Ajaxian has been one of the best news I could read about HTML5 specs and browsers evolution.
I could not wait to download Safari 4 and test instantly this feature.
I have always been interested in this possibility, both progress bar, plus multiple uploads and that's why I would like to add this post to this list:


First Step: The Input Type File

We can create a multiple input files in different ways: directly in the layout

<input type="file" multiple="multiple" />

or via JavaScript:

var input = document.createElement("input");
input.setAttribute("type", "file");
input.setAttribute("multiple", "multiple"); // note: input.multiple = "multiple" does not work in Safari 4 beta

I know we all like graceful degradation, but in this post I will only talk about a client side progress bar, something that is cool and possible, so far, only via JavaScript ;-)


Second Step: XMLHttpRequest Version 2

The last implementation of this constructor brings some cool stuff with him, the XMLHttpRequestUpload interface, used by an automatic created property called upload.
The reason this property is as cool as welcome, is that it can trace sent binary data via dispatched events like onload, onprogress, and others.

var xhr = new XMLHttpRequest,
upload = xhr.upload;
upload.onload = function(){
console.log("Data fully sent");
};
xhr.open("post", page, true);
xhr.send(binaryData);

Above snippet is the basis of the new feature introduced by Safari 4, feature better explained in the dedicated example I prepared for this post.


Third Step: The PHP Manager

If we use multiple attribute without XMLHttpRequest, we simply need to set a name, and manage data in the server via the superglobal $_FILES. But if we want to send directly the binary stream, the only thing we need to do in the server, security checks a part, is to save the content sent via input:

<?php
// e.g. url:"page.php?upload=true" as handler property
if(isset($_GET['upload']) && $_GET['upload'] === 'true'){
$headers = getallheaders();
if(
// basic checks
isset(
$headers['Content-Type'],
$headers['Content-Length'],
$headers['X-File-Size'],
$headers['X-File-Name']
) &&
$headers['Content-Type'] === 'multipart/form-data' &&
$headers['Content-Length'] === $headers['X-File-Size']
){
// create the object and assign property
$file = new stdClass;
$file->name = basename($headers['X-File-Name']);
$file->size = $headers['X-File-Size'];
$file->content = file_get_contents("php://input");

// if everything is ok, save the file somewhere
if(file_put_contents('files/'.$file->name, $file->content))
exit('OK');
}

// if there is an error this will be the output instead of "OK"
exit('Error');
}
?>



Last Step: The Client Manager With The Progress Bar

This is the last thing we should care about, and only after we are sure we implemented best security checks to avoid problems for users and the server itself. In this example I did not implement too many checks, so please take it as a hint, rather than a final solution for public production environments.
The client side is really simple and entirely managed via JavaScript.

/** basic Safari 4 multiple upload example
* @author Andrea Giammarchi
* @blog WebReflection [webreflection.blogspot.com]
*/
onload = function(){

function size(bytes){ // simple function to show a friendly size
var i = 0;
while(1023 < bytes){
bytes /= 1024;
++i;
};
return i ? bytes.toFixed(2) + ["", " Kb", " Mb", " Gb", " Tb"][i] : bytes + " bytes";
};

// create elements
var input = document.body.appendChild(document.createElement("input")),
bar = document.body.appendChild(document.createElement("div")).appendChild(document.createElement("span")),
div = document.body.appendChild(document.createElement("div"));

// set input type as file
input.setAttribute("type", "file");

// enable multiple selection (note: it does not work with direct input.multiple = true assignment)
input.setAttribute("multiple", "multiple");

// auto upload on files change
input.addEventListener("change", function(){

// disable the input
input.setAttribute("disabled", "true");

sendMultipleFiles({

// list of files to upload
files:input.files,

// clear the container
onloadstart:function(){
div.innerHTML = "Init upload ... ";
bar.style.width = "0px";
},

// do something during upload ...
onprogress:function(rpe){
div.innerHTML = [
"Uploading: " + this.file.fileName,
"Sent: " + size(rpe.loaded) + " of " + size(rpe.total),
"Total Sent: " + size(this.sent + rpe.loaded) + " of " + size(this.total)
].join("<br />");
bar.style.width = (((this.sent + rpe.loaded) * 200 / this.total) >> 0) + "px";
},

// fired when last file has been uploaded
onload:function(rpe, xhr){
div.innerHTML += ["",
"Server Response: " + xhr.responseText
].join("<br />");
bar.style.width = "200px";

// enable the input again
input.removeAttribute("disabled");
},

// if something is wrong ... (from native instance or because of size)
onerror:function(){
div.innerHTML = "The file " + this.file.fileName + " is too big [" + size(this.file.fileSize) + "]";

// enable the input again
input.removeAttribute("disabled");
}
});
}, false);

bar.parentNode.id = "progress";

};

The external file with sendFile and sendMultipleFile function is in my repository and in the attached zip, while a workable example page with a limit of 1Mb for each file is here in my host.