How to Upload Multiple Files Using One File Input Element

How to upload multiple files using one file input element

The multiple file select in the dialog when you click on the browse button of the file field happens only for the new browsers supporting HTML5. It wont allow multiple select for old browsers. For older browsers the only good solutions are flash or javascript plugins. Here is a good resource for jquery uploaders ( some support multiple files ): http://creativefan.com/10-ajax-jquery-file-uploaders/. Hence my suggestion is use some plugin so that its supported on old as well as the new browsers.

How to select multiple files with <input type=file>?

New answer:

In HTML5 you can add the multiple attribute to select more than 1 file.

<input type="file" name="filefield" multiple="multiple">

Old answer:

You can only select 1 file per <input type="file" />. If you want to
send multiple files you will have to use multiple input tags or use
Flash or Silverlight.

Upload multiple files with a single input element

You can use the <input type="file"> with the multiple attribute.

<input name="sliderfile" id="sliderfile" type="file" multiple>

jsFiddle Example.

Note: IE6 won't like it.

How to add/upload/choose multiple files from one input tag?

You can hide the input[type=file] and provide an UI that interacts with the input in order to select new files and manage separately a list of files.

So you can:

  1. add a hidden input <input id="myInput" type="file" multiple style="display:none" />

  2. Provide a good looking UI with a button that calls the myInput.click() in order to open the prompt

  3. subscribe to input change event and get the myInput.files and store them in an array or collection

  4. to upload all files via AJAX just create a FormData and append all the files then pass FormData instance to the ajax call (eg: $ajax({...data: formData...})).

EDITED:

Plnkr link

Sample Behavior:

  • Pressing "+ Add Files" button will add new files to the list.
  • Clicking a file in the list will remove the file
  • Pressing "Send Files" button will send the files to the corresponding URL

Sample HTML:

<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8" />
<title></title>
<link rel="stylesheet" href="style.css" />
<script data-require="jquery" data-semver="3.1.1" src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="script.js"></script>
</head>

<body>
<input id="myInput" type="file" multiple style="display:none" />

<button id="myButton" type="button" style="border-radius: 5px; background-color: #fff; color: green;">+ Add Files</button>
<button id="mySubmitButton" type="button" style="border-radius: 5px; background-color: #fff; color: green;">Send Files</button>

<div id="myFiles"></div>
</body>

</html>

Sample Script:

$(function(){
let inputFile = $('#myInput');
let button = $('#myButton');
let buttonSubmit = $('#mySubmitButton');
let filesContainer = $('#myFiles');
let files = [];

inputFile.change(function() {
let newFiles = [];
for(let index = 0; index < inputFile[0].files.length; index++) {
let file = inputFile[0].files[index];
newFiles.push(file);
files.push(file);
}

newFiles.forEach(file => {
let fileElement = $(`<p>${file.name}</p>`);
fileElement.data('fileData', file);
filesContainer.append(fileElement);

fileElement.click(function(event) {
let fileElement = $(event.target);
let indexToRemove = files.indexOf(fileElement.data('fileData'));
fileElement.remove();
files.splice(indexToRemove, 1);
});
});
});

button.click(function() {
inputFile.click();
});

buttonSubmit.click(function() {
let formData = new FormData();

files.forEach(file => {
/* here I just put file as file[] so now in submitting it will send all
files */
formData.append('file[]', file);
});

console.log('Sending...');

$.ajax({
url: 'https://this_is_the_url_to_upload_to',
data: formData,
type: 'POST',
success: function(data) { console.log('SUCCESS !!!'); },
error: function(data) { console.log('ERROR !!!'); },
cache: false,
processData: false,
contentType: false
});
});
});

Handling multiple files uploaded through POST from single input element

For anyone else who might have this issue. After some more searching, I found the answer here: uploading-multiple-files-using-formdata

I had to modify my formData.append command a little bit and iterate through the array instead of just passing the whole thing:

var entryArray = new Array("entryName","entryFoodType","entryROI","entryOpeningHour","entryOpeningMinute","entryOpeningAMPM","entryClosingHour","entryClosingMinute","entryClosingAMPM","entryPhone","entryEmail","entryPhotos","entryDesc","entryLocLat","entryLocLong");
for(var temp = 0; temp < entryArray.length; temp++){
if($('#' + entryArray[temp])[0].files){
for (var i = 0; i < $('#' + entryArray[temp])[0].files.length; i++) {
formData.append(entryArray[temp] + "[]", $('#' + entryArray[temp])[0].files[i]);
}
}
else{
formData.append(entryArray[temp], $('#' + entryArray[temp]).val());
}
}

And for completion's sake if it may help someone in the future, to process on the server in PHP:

for($i = 0; $i < count($_FILES["entryPhotos"]["name"]); $i++){
$tmp_name = $_FILES["entryPhotos"]["tmp_name"][$i];
if (!$tmp_name) continue;

$name = basename($_FILES["entryPhotos"]["name"][$i]);

if ($_FILES["entryPhotos"]["error"][$i] == UPLOAD_ERR_OK)
{
if ( move_uploaded_file($tmp_name, $uploaddir.$name) ){
echo 'us';
}
else{
echo 'uf';
}
}
else{
echo 'uf';
}
}

EDIT/NOTE: This upload script is rather crude and has certain security risks. Always keep in mind when uploading files: Never trust what a user is uploading is safe. Always sanitize your uploads best you can. One thing that isn't shown in this snippet is that the files are kept in a folder behind the webroot. This helps prevent access from a potential hacker from a script they might upload.

It is also recommended to change the name of the file all together to something random and unique and at the same time, check the file extension(s). Some servers are set to allow multiple extensions and this can give an opening. There are a few ways I found online to do these things and after mixing them together this is what I came up with:

In order to get a random and unique name I used $prefix = str_replace(array('.', ' '), '' , microtime()); which pulls the current Unix time in microseconds, thus giving a number a potential hacker wouldn't be able to predict as easily, then to help ensure uniqueness since I am looping through multiple files I added the index of the loop to the end of the prefix.

Then I pulled the extension(s) of the basename. Instead of using the typical pathinfo() to pull the extension, I used strstr(basename($name), '.'). The advantage I find with this is it will pull all file extensions, not just the last. Then I check that against a list of accepted extensions. If it passes then it may be uploaded to a directory prior to the webroot. An extra step this inherently takes is if the file has multiple extensions it is automatically skipped, avoiding the possible security risk there.

One last note is that there are a couple of "sanitation" techniques that I did not use such as checking for an image size and checking the MIME type to verify the files are images. Actual images (thus returning a file size) can contain malicious coding and the MIME type is sent by the client and thus can be faked. These to me seemed to give no actual benefit so I did not use them but some may argue that there is no such thing as being too secure, and there are even further measures that could be taken. When dealing with user input, in any way, you should always do as much research as possible and take appropriate precautions to make sure you, your data and your users are protected.

How can I select and upload multiple files with HTML and PHP, using HTTP POST?

This is possible in HTML5. Example (PHP 5.4):

<!doctype html>
<html>
<head>
<title>Test</title>
</head>
<body>
<form method="post" enctype="multipart/form-data">
<input type="file" name="my_file[]" multiple>
<input type="submit" value="Upload">
</form>
<?php
if (isset($_FILES['my_file'])) {
$myFile = $_FILES['my_file'];
$fileCount = count($myFile["name"]);

for ($i = 0; $i < $fileCount; $i++) {
?>
<p>File #<?= $i+1 ?>:</p>
<p>
Name: <?= $myFile["name"][$i] ?><br>
Temporary file: <?= $myFile["tmp_name"][$i] ?><br>
Type: <?= $myFile["type"][$i] ?><br>
Size: <?= $myFile["size"][$i] ?><br>
Error: <?= $myFile["error"][$i] ?><br>
</p>
<?php
}
}
?>
</body>
</html>

Here's what it looks like in Chrome after selecting 2 items in the file dialog:

chrome multiple file select

And here's what it looks like after clicking the "Upload" button.

submitting multiple files to PHP

This is just a sketch of a fully working answer. See PHP Manual: Handling file uploads for more information on proper, secure handling of file uploads in PHP.

How to upload files using multiple files input element?

You need to call the file fields different things for the different categories, for example:

    var a_pics = fileService.getFile($scope.a_pics);
var b_pics = fileService.getFile($scope.b_pics);

var option = {
transformRequest: angular.identity,
headers: {'Content-Type': plan_pics.type}
};

var fd = new FormData();
var index;

for (index = 0; index < a_pics.length; index++)
fd.append('files_a', a_pics[index]);
for (index = 0; index < b_pics.length; index++)
fd.append('files_b', b_pics[index]);

$http.post('/api/projects', fd, option);

Then you'll get two different field names in your submitted data, and can handle that appropriately in your server code.



Related Topics



Leave a reply



Submit