Keep Directory Structure When Uploading
So lately I’ve been playing around a lot with the new File API and some image manipulation etc. in javascript and am having tremendous fun doing so!
I’ve seen many people asking about folder uploading, which is an exciting new development. The problem most people seem to be having is with retaining file structures when uploading folders.
It is possible to retain the structure of folders during uploading. At the point of writing, I have been unable to find an equivalent for browsers that do not use webkit.
This post is for TESTING ONLY.
I’m working on a full AJAX folder upload script, but as I go, I’ll try to post little snippets I find interesting!
So, without further ado, the code:
<input type="file" id="files" name="files[]" multiple webkitdirectory />
document.getElementById('files').onchange = function(e) { var files = e.target.files; // FileList for (var i = 0, f; f = files[i]; ++i) console.debug(files[i].webkitRelativePath); }
Retrieving the paths is as simple as that!
And here’s a working example:
This is the most basic version and will display a list of the submitted.
The fiddle is slightly more complex than the code above to allow it to be displayed without consoles and whatnot.
Uploading This To The Server!
Things start getting slightly more complex when we come to uploading this to the server.
As far as I’ve been able to find at the time of writing, HTTP request does not support the transfer of file paths when uploading. This can be easily resolved by adding it into the request data ourselves.
function uploadFiles(files){ // Create a new HTTP requests, Form data item (data we will send to the server) and an empty string for the file paths. xhr = new XMLHttpRequest(); data = new FormData(); paths = ""; // Set how to handle the response text from the server xhr.onreadystatechange = function(ev){ console.debug(xhr.responseText); }; // Loop through the file list for (var i in files){ // Append the current file path to the paths variable (delimited by tripple hash signs - ###) paths += files[i].webkitRelativePath+"###"; // Append current file to our FormData with the index of i data.append(i, files[i]); }; // Append the paths variable to our FormData to be sent to the server // Currently, As far as I know, HTTP requests do not natively carry the path data // So we must add it to the request manually. data.append('paths', paths); // Open and send HHTP requests to upload.php xhr.open('POST', "upload.php", true); xhr.send(this.data); }
This will simply create a triple hash delimited string which we will split into an array of file paths on the server which will correspond to our array of files.
<?php if(sizeof($_FILES) > 0) $fileUploader = new FileUploader($_FILES); class FileUploader{ public function __construct($uploads,$uploadDir='uploads/'){ // Split the string containing the list of file paths into an array $paths = explode("###",rtrim($_POST['paths'],"###")); // Loop through files sent foreach($uploads as $key => $current) { // Stores full destination path of file on server $this->uploadFile=$uploadDir.rtrim($paths[$key],"/."); // Stores containing folder path to check if dir later $this->folder = substr($this->uploadFile,0,strrpos($this->uploadFile,"/")); // Check whether the current entity is an actual file or a folder (With a . for a name) if(strlen($current['name'])!=1) // Upload current file if($this->upload($current,$this->uploadFile)) echo "The file ".$paths[$key]." has been uploadedn"; else echo "Error"; } } private function upload($current,$uploadFile){ // Checks whether the current file's containing folder exists, if not, it will create it. if(!is_dir($this->folder)){ mkdir($this->folder,0700,true); } // Moves current file to upload destination if(move_uploaded_file($current['tmp_name'],$uploadFile)) return true; else return false; } } ?>
Progress
This is by no means perfect, this is just something I’ve been playing around with and felt like sharing my findings. I’ll be updating this post when I have more to post. Or if it’s something especially exciting, I may even make a new post
So for now, have fun and find the archived source here!
Source
Pingback: Sapphion » HTML5 Upload Folder With Webkitdirectory
I’ve downloaded the package and tried to upload 6 pics of different types, but it doesn’t work, without any prompt. I used it in IE, in firefox and in google-chrome. None of them worked!
my fault… it worked! Thanks
Sorry I wasn’t around to help but I’m glad you worked it out!
If you have a minute, could you tell me what had caused it to not work?
It might be helpful to add a note to the demo in case someone else does the same thing.
hi, Alan it was great! thanks a lot…
How can i show the progress bar in the above for uploading the directory
R u sure it will work in linux evironment?
Hi, the operating system shouldn’t have any affect on this. However – This does not work in Firefox which is the default browser in Linux. I’ll look over this and see if I can get a simple solution in Firefox.
I feel like this is probably due an update anyway.
Doesnt Work with pics & not working in firefox….
please help
As far as I’m aware, currently only Chrome has an implementation of this. So I’m afraid I can’t help.
Hello Alan
We it seems theres some bug in the code,can you help me out? It works fine but when I try to send a folder to the server(localhost:xampp) with 25 files it only sends 20, theres always some missing like that. can you check it out please?
Awsome work otherwise (y)
Hi Hamza,
While there are undoubtedly upload limits associated with this script, I believe the problem you are encountering is down to PHP its self.
http://www.php.net/manual/en/ini.core.php#ini.max-file-uploads
This setting defaults to 20 and is probably causing your problems.
Cheers