Reputation: 1471
var fd = new FormData();
fd.append("fileToUpload", document.getElementById('fileToUpload').files[0]);
var xhr = new XMLHttpRequest();
xhr.open("POST", "uph.php");
xhr.send(fd);
uph.php:
var_dump($_FILES['fileToUpload']);
This works, but obviously for the files[0]
only. How to get this working for chosen file?
I tried removing the [0]
, but it didn't work.
Upvotes: 147
Views: 373912
Reputation: 178
In my case, I was getting Arrays are not supported
error after calling form.append()
with different files with different names.
Here's the code snippet:
form.append('prompttemplate', promptTemplate, {
filename: 'prompttemplate.txt',
contentType: 'text/plain',
});
ERROR HERE: ---
form.append('datafile', dataFile, {
filename: 'datafile.json',
contentType: 'text/plain',
});
It was failing on the second call leading me to believe that there was something wrong with adding more than one file type.
Error: Arrays are not supported. at FormData.append
However, upon further inspection into the base code:
You will see that the error is talking about the type of the second parameter itself; the value.
Upon further inspection, I was attempting to add an array of objects when my intent was to just send the JSON string of that object.
Basically, I had forgotten to stringify the JSON before adding it and that object was an array and that's what the error message was referring to.
It would have saved me a lot of time if it had said:
"Arrays are not supported in the parameter value
"
Once I converted my object to a JSON stringified string, everything worked as expected.
Lesson: Be careful what you take the error message to mean and maybe dig into the library source code a little.
Upvotes: 1
Reputation: 1577
You have to use files.length
to append in JavaScript, and then send it via an Ajax request:
JavaScript:
var files = document.getElementById('fileToUpload').files;
for (var x = 0; x < files.length; x++) {
fd.append("fileToUpload[]", files[x]);
}
PHP:
$count = count($_FILES['fileToUpload']['name']);
for($i = 0; $i < $count; $i++){
echo 'Name: '.$_FILES['fileToUpload']['name'][$i].'<br/>';
}
Upvotes: 153
Reputation: 943
In React & Typescript app use the same key for each file, server will treat it as array:
const formData = new FormData();
if (state.files && state.files.length > 0) {
state.files.forEach((file: File) => {
// Use the same key 'files' for each file
formData.append('files', file);
});
}
Upvotes: 0
Reputation: 1
var fd = new FormData();
//assuming file inputs have a common classname (always easier when they do)
var fileInputs = document.querySelectorAll('.fileToUpload');
var fileInputsArray = Array.from(fileInputs);
//"upload" is the parameter you may chose to store the files
fileInputsArray.forEach((element, index) => {
fd.append(`upload[${index}]`, element.files[0])
});
//do your ajax here
//you could use fetch as well
fetch(`${origin}`/api_uri,{
method: "POST",
body: fd,
headers: {
Accept: "application/json"
},
})
Upvotes: 0
Reputation: 391
If we have input in our html:
<input id="my-input" type="file" mutliple /> // multiple attribute to select and upload multiple files
We can get files from that input and send it to server with pure js script:
const myInput = document.getElementById('my-input') // getting our input
myInput.addEventListener('change', (event) => { // listening for file uploads
const files = event.target.files // getting our files after upload
const formData = new FormData() // create formData
for (const file of files) {
formData.append('files', file) // appending every file to formdata
}
const URL = 'http://api.server.com'
const response = fetch(URL, {
method: 'POST',
data: formData // sending our formdata in body of post request
})
return response.json()
}
It worked perfect for me
P.S.: I used multer
in backend (node.js + express), added to file upload route
upload.array("files", 10)
Upvotes: 4
Reputation: 1176
Appending multiple files to the same key didn't work for me. I ended up appending them separately.
files.forEach((file) => {
formData.append(`file-${file.name}`, file);
})
Upvotes: 0
Reputation: 326
This worked for me also:
var data = new FormData();
for (const key in files)
data.append('gallery[]',files[key])
Upvotes: 4
Reputation: 11
let fd = new FormData();
fd.append( "images" , image1 );
fd.append( "images" , image2 );
fd.append( "images" , image3 );
In this format you can send multiple file by axios. But i had some problem with this. only one file was uploaded when i try to append in form data and try to send this through axios. and my problem was that i had imported {Axios} from 'axios' but it will not gonna work. we have to import axios from 'axios' ( look at the spelling ) then it was work perfectly for me
Upvotes: 1
Reputation: 142
If you are instantiating the FormData object already passing the form as a constructor parameter, the input file's name attribute must contain the square brackets.
HTML:
<form id="myForm" method="POST" action="url" enctype="multipart/form-data">
<input class="form-control form-control-lg" type="file" name="photos[]" multiple />
JS:
var formData = new FormData(document.getElementById('myForm'));
console.log(formData.getAll('photos[]'));
That worked for me!
Upvotes: 4
Reputation: 617
This worked for me
var ins = $('.file').map(function () {
return this.files;
}).get();
for (var x = 0; x < ins; x++) {
formData.append("file", ins[x][0]);
}
Upvotes: 5
Reputation: 111
I worked that such as:
var images = document.getElementById('fileupload').files;
var formData = new FormData();
for(i=0; i<images.length; i++) {
formData.append('files', images[i]);
}
Upvotes: 6
Reputation: 745
Adding []
when appending to fd works, but if you prefer to have your data grouped by file then I'd suggest doing it this way:
var files= document.getElementById('inpFile').files
var fd = new FormData()
for (let i = 0; i < files.length; i++) {
fd.append(i, files[i])
}
Now your data will be sent grouped by file instead of grouped by attribute.
Upvotes: 9
Reputation: 2298
The way to go with javascript:
var data = new FormData();
$.each($("input[type='file']")[0].files, function(i, file) {
data.append('file', file);
});
$.ajax({
type: 'POST',
url: '/your/url',
cache: false,
contentType: false,
processData: false,
data : data,
success: function(result){
console.log(result);
},
error: function(err){
console.log(err);
}
})
If you call data.append('file', file) multiple times your request will contain an array of your files.
"The
append()
method of theFormData
interface appends a new value onto an existing key inside aFormData
object, or adds the key if it does not already exist. The difference betweenFormData.se
t andappend()
is that if the specified key already exists,FormData.set
will overwrite all existing values with the new one, whereasappend()
will append the new value onto the end of the existing set of values."
Myself using node.js and multipart handler middleware multer get the data as follows:
router.post('/trip/save', upload.array('file', 10), function(req, res){
// Your array of files is in req.files
}
Upvotes: 107
Reputation: 111
To upload multiple files with angular form data, make sure you have this in your component.html
Upload Documents
<div class="row">
<div class="col-md-4">
<small class="text-center"> Driver Photo</small>
<div class="form-group">
<input (change)="onFileSelected($event, 'profilepic')" type="file" class="form-control" >
</div>
</div>
<div class="col-md-4">
<small> Driver ID</small>
<div class="form-group">
<input (change)="onFileSelected($event, 'id')" type="file" class="form-control" >
</div>
</div>
<div class="col-md-4">
<small>Driving Permit</small>
<div class="form-group">
<input type="file" (change)="onFileSelected($event, 'drivingpermit')" class="form-control" />
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<small>Car Registration</small>
<div class="form-group">
<div class="input-group mb-4">
<input class="form-control"
(change)="onFileSelected($event, 'carregistration')" type="file"> <br>
</div>
</div>
</div>
<div class="col-md-6">
<small id="li"> Car Insurance</small>
<div class="form-group">
<div class="input-group mb-4">
<input class="form-control" (change)="onFileSelected($event,
'insurancedocs')" type="file">
</div>
</div>
</div>
</div>
<div style="align-items:c" class="modal-footer">
<button type="button" class="btn btn-secondary" data-
dismiss="modal">Close</button>
<button class="btn btn-primary" (click)="uploadFiles()">Upload
Files</button>
</div>
</form>
In your componenet.ts file declare array selected files like this
selectedFiles = [];
// array of selected files
onFileSelected(event, type) {
this.selectedFiles.push({ type, file: event.target.files[0] });
}
//in the upload files method, append your form data like this
uploadFiles() {
const formData = new FormData();
this.selectedFiles.forEach(file => {
formData.append(file.type, file.file, file.file.name);
});
formData.append("driverid", this.driverid);
this.driverService.uploadDriverDetails(formData).subscribe(
res => {
console.log(res);
},
error => console.log(error.message)
);
}
NOTE: I hope this solution works for you friends
Upvotes: 1
Reputation: 9
I found this work for me!
var fd = new FormData();
$.each($('.modal-banner [type=file]'), function(index, file) {
fd.append('item[]', $('input[type=file]')[index].files[0]);
});
$.ajax({
type: 'POST',
url: 'your/path/',
data: fd,
dataType: 'json',
contentType: false,
processData: false,
cache: false,
success: function (response) {
console.log(response);
},
error: function(err){
console.log(err);
}
}).done(function() {
// do something....
});
return false;
Upvotes: 0
Reputation: 31
Here is the Vanilla JavaScript solution for this issue -
First, we'll use Array.prototype.forEach()
method, as
document.querySelectorAll('input[type=file]')
returns an array like object.
Then we'll use the Function.prototype.call()
method to assign each element in the array-like object to the this
value in the .forEach
method.
HTML
<form id="myForm">
<input type="file" name="myFile" id="myFile_1">
<input type="file" name="myFile" id="myFile_2">
<input type="file" name="myFile" id="myFile_3">
<button type="button" onclick="saveData()">Save</button>
</form>
JavaScript
function saveData(){
var data = new FormData(document.getElementById("myForm"));
var inputs = document.querySelectorAll('input[type=file]');
Array.prototype.forEach.call(inputs[0].files, function(index){
data.append('files', index);
});
console.log(data.getAll("myFile"));
}
You can view the working example of the same HERE
Upvotes: 1
Reputation: 15578
Create a FormData
object
const formData: any = new FormData();
And append to the same keyName
photos.forEach((_photoInfo: { localUri: string, file: File }) => {
formData.append("file", _photoInfo.file);
});
and send it to server
// angular code
this.http.post(url, formData)
this will automatically create an array of object under file
if you are using nodejs
const files :File[] = req.files ? req.files.file : null;
Upvotes: 0
Reputation: 169
This one worked for me
//Javascript part
//file_input is a file input id
var formData = new FormData();
var filesLength=document.getElementById('file_input').files.length;
for(var i=0;i<filesLength;i++){
formData.append("file[]", document.getElementById('file_input').files[i]);
}
$.ajax({
url: 'upload.php',
type: 'POST',
data: formData,
contentType: false,
cache: false,
processData: false,
success: function (html) {
}
});
<?php
//PHP part
$file_names = $_FILES["file"]["name"];
for ($i = 0; $i < count($file_names); $i++) {
$file_name=$file_names[$i];
$extension = end(explode(".", $file_name));
$original_file_name = pathinfo($file_name, PATHINFO_FILENAME);
$file_url = $original_file_name . "-" . date("YmdHis") . "." . $extension;
move_uploaded_file($_FILES["file"]["tmp_name"][$i], $absolute_destination . $file_url);
}
Upvotes: 11
Reputation: 497
This worked for me:
let formData = new FormData()
formData.append('files', file1)
formData.append('files', file2)
Upvotes: 28
Reputation: 106
This worked fine !
var fd = new FormData();
$('input[type="file"]').on('change', function (e) {
[].forEach.call(this.files, function (file) {
fd.append('filename[]', file);
});
});
$.ajax({
url: '/url/to/post/on',
method: 'post',
data: fd,
contentType: false,
processData: false,
success: function (response) {
console.log(response)
},
error: function (err) {
console.log(err);
}
});
Upvotes: 5
Reputation: 510
You just have to use fileToUpload[]
instead of fileToUpload
:
fd.append("fileToUpload[]", document.getElementById('fileToUpload').files[0]);
And it will return an array with multiple names, sizes, etc...
Upvotes: 28