Browser Folder Uploading
You have to add some parameters to the input tag to support directory uploads: webkitdirectory
for Webkit-based browsers (e.g., Chrome) and mozdirectory
for Mozilla's browser (Firefox).
The HTML code could look like this:
<input type="file" webkitdirectory mozdirectory … />
You could have a look at https://stackoverflow.com/a/46562869 and https://stackoverflow.com/a/8218074, which are answers to similar questions.
How to Upload a Full Folder with their files
In modern Chrome, Firefox, and Edge you can set a html attribute, webkitdiretory
to let the file input become a directory select window instead. And if you also use the multiple
attribute after selecting the folder all contents (and contents in subfolders) will be in the .files
list
<input type="file" webkitdirectory multiple>
You would then just use the same code to include all the files for upload.
Now if you want to keep the folder structure you would have to also include the webkitRelativePath
which holds the relative path for that file within the folder you selected. And use that path to create the folders on the server.
for (let i = 0; i < files.length; i++) {
let file = files[i];
let fileParamName = `file${i}`;
let filePathParamName = `filepath${i}`;
formData.append(fileParamName, file);
formData.append(filePathParamName,file.webkitRelativePath);
}
And then on the server use filePathParamName to make the directory structure and move the file to it:
//Just for example
//make sure to used sanitized data in production
$folderpath = $path.dirname($_POST["filepath23"]);
$file = $path.$_POST["filepath23"];
$file_tmp = $_FILES["file23"]["tmp_name"];
//third option is for recursive folder creation (make subfolders)
mkdir($path,0644,true);
move_uploaded_file($file_tmp, $file)
For an easier method you could put all the files into a zip file within javascript and just upload the single zip file and extract on the server. Using JSZip and PHP ZipArchive class:
var zip = new JSZip();
for (let i = 0; i < files.length; i++) {
let file = files[i];
zip.file(file.webkitRelativePath, file);
}
zip.generateAsync({type:"blob"})
.then(function(content) {
formData.append("folderzip",content);
fetch(url, {
method: 'POST',
body: formData
}).then(response => {
console.log(response);
});
});
Then in php unzip the folder to where you want it:
move_uploaded_file($file_tmp, $path);
$zip = new ZipArchive();
if($zip->open($path)){
$zip->extractTo($somepath);
$zip->close();
//delete zip file
unlink($path);
}
Client side demo of file listing using webkitRelativePath:
var output = document.querySelector("#output");document.querySelector("input").onchange = function() { var files = this.files; for (file of files) { output.insertAdjacentHTML('beforeend', `<div>${file.webkitRelativePath}</div>`); }}
<input type="file" webkitdirectory multiple>
<div id="output"></div>
Related Topics
How Does One Use the Onerror Attribute of an Img Element
Why Does Inline-Block Cause This Div to Have Height
Why Does Overflow Hidden Stop Floating Elements Escaping Their Container
Youtube: How to Present Embed Video with Sound Muted
How to Resize an Image to Fit in the Browser Window
Adding Custom Attribute (Html5) Support to Jsf 2.0 Uiinput Component
Does the <Li> Tag in HTML Have an Ending Tag
CSS Grid - Maximum Number of Columns Without Media Queries
Image Width/Height as an Attribute or in CSS
How to Isolate a Div from Public CSS Styles
Unskewing the Ends of an Assortment Multiple Skewed Images
Why Does My Transform Snap Back
Html5 Email Input Pattern Attribute
HTML Auto Embedding Recent Uploaded Videos from a Youtube Channel