I have method which detects files (in this case images):
detectFiles(event) {
this.formData = new FormData();
this.urls = [];
this.files = event.target.files;
if (this.files) {
for (const file of this.files) {
const reader = new FileReader();
reader.onload = (e: any) => {
this.urls.push(e.target.result);
};
reader.readAsDataURL(file);
}
}}
the files I've got are saved in this.files and on submit button I do this:
submitForm(value: any) {
if (value) {
this.formData.append('Title', value.title);
this.formData.append('Date', value.date);
for (let i = 0; i < this.files.length; i++) {
const chosenFileName = this.files[i].name;
const chosenFile = this.files[i];
this.formData.append('file', chosenFileName, chosenFile);
}
this.authService.uploadFile(this.formData)
.subscribe(
(response) => {
},
(error) => {
}
);
}}
here, I add values from input and then go through loop to add all the files I've got.
In the example, I added to pictures, however they did not appear in the request.
What am I doing wrong here?
The mistake was a dummy one:
for (let i = 0; i < this.files.length; i++) {
const chosenFileName = this.files[i].name;debugger;
const chosenFile = this.files[i];
this.formData.append('file', chosenFile); // <----- changed this line
}
Related
I want to download all audio files from folder but this code only download last file in folder.
var element = document.getElementById("songs");
var audionum = element.getElementsByTagName('audio').length;
var zipcounter = 0;
var zip = new JSZip();
var zipName = 'Test.zip';
for(var i = 0; i < audionum; i++){
var audiosrc = document.getElementsByTagName('source')[i].getAttribute("src");
var audiosrcsplit = audiosrc.split('/')[1];
// loading a file and add it in a zip file
JSZipUtils.getBinaryContent(audiosrc, function (err, data) {
if(err) {
throw err; // or handle the error
}
zip.file(audiosrcsplit, data, {binary:true});
zipcounter++;
if (zipcounter == audionum) {
zip.generateAsync({type:'blob'}).then(function(content) {
saveAs(content, zipName);
});
}
});
}
For ES6 , you can try replacing var with let (block scope).
If you are making use of ES5 then, try something like below.
var element = document.getElementById("songs");
var audionum = element.getElementsByTagName('audio').length;
var zipcounter = 0;
var zip = new JSZip();
var zipName = 'Test.zip';
function addToZip(audiosrc, audiosrcsplit) {
JSZipUtils.getBinaryContent(audiosrc, function (err, data) {
if (err) {
throw err; // or handle the error
}
zip.file(audiosrcsplit, data, {
binary: true
});
zipcounter++;
if (zipcounter == audionum) {
zip.generateAsync({
type: 'blob'
}).then(function (content) {
saveAs(content, zipName);
});
}
});
}
for (var i = 0; i < audionum; i++) {
var audiosrc = document.getElementsByTagName('source')[i].getAttribute("src");
var audiosrcsplit = audiosrc.split('/')[1]; // loading a file and add it in a zip file
addToZip(audiosrc, audiosrcsplit);
}
I have implemented Drag and Drop File Upload in my react project, so on every drag and drop of file into the drop zone , I'm taking the file and accessing it's name and it's data and converting the data to base64 using javscript's FileReader() and readAsDataURL() and updating the state, which I need to send it to bakend.
How to append a number to filename if the file with same name already exist in the state ?
eg: file(1).csv or file 2.csv
Main State
this.state : {
Files:[],
}
Function that get's triggered every time for drag and drop of file
FileHandling = (files) => {
files.forEach((file) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
const CompleteData= {
fileData: reader.result,
fileName: file.name,
};
this.setState({
Files:[...this.state.Files, CompleteData]
})
};
});
};
Make any pattern that you want on the line with a comment.
const getUniqueName = (fileName, index = 0) => {
let checkName = fileName, ext = '';
if(index){
if(checkName.indexOf('.') > -1){
let tokens = checkName.split('.'); ext = '.' + tokens.pop();
checkName = tokens.join('.');
}
// make any pattern here
checkName = `${checkName} (${index})${ext}`;
}
const nameExists = this.state.Files.filter(f=>f.fileName === checkName).length > 0;
return nameExists ? getUniqueName(fileName, index + 1) : checkName;
}
FileHandling = (files) => {
files.forEach((file) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
const CompleteData = {
fileData: reader.result,
fileName: getUniqueName(file.name),
};
this.setState({
Files:[...this.state.Files, CompleteData]
})
};
});
};
You can check this.state.Files before. A recursive function could be used here. Imagine you load a file named export.csv. The second one would export.csv transformed in export_1.csv. But on a third one named export.csv, the verification would be done on export, leading to export_1 => Error !
The best is to do :
const checkNameOfTheFile = (newFileName) => {
// Ex 'export.csv'
const counter = this.state.Files.filter(f => f.fileName === newFileName).length;
// If counter >= 2, an error has already been passed to the files because it means
// 2 files have the same name
if (counter >= 2) {
throw 'Error duplicate name already present';
}
if (counter === 0) {
return newFileName
}
if (counter === 1) {
const newName = `${newFileName.split('.')[0]}_${counter}.${newFileName.split('.')[1]}`;
// Return export_1.csv;
return checkNameOfTheFile(newName);
// We need to check if export_1.csv has not been already taken.
// If so, the new name would be export_1_1.csv, not really pretty but it can be changed easily in this function
}
};
const CompleteData= {
fileData: reader.result,
fileName: checkNameOfTheFile(file.name),
};
Determine if there is a matching file, if so determine if it is already a duplicate (has a number at the end already). If so find its number and increment it. Otherwise just append a '1'. If there are no matching files, don't do anything.
FileHandling = (files) => {
files.forEach((file) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
let existingFiles = this.state.Files.filter(x=>x.fileName==file.Name);
let fileName = file.Name;
if(existingFiles.length > 0) {
let oldFileName = existingFiles[0].split('.')[0];
let oldFileMatchNumberMatch = oldFileName.match(/\d+$/);
let fileNumber = (oldFileMatchNumberMatch) parseInt(oldFileMatchNumberMatch[0], 10) : 1;
fileName = file.Name + fileNumber; //if file.Name has an extension, you'll need to split, add the number to the end of the 0'th element, and rejoin it
}
const CompleteData= {
fileData: reader.result,
fileName: file.name,
};
this.setState({
Files:[...this.state.Files, CompleteData]
})
};
});
Ok, It's not exactly in the format of the question, but it seems to me that it can help.
Below is a simple js code, which goes through a list of strings representing file names, and computes the next name.
If the file 'file.png' exists once - it will be returned 'file(1).png'.
If the file 'file(1).png' also exists- it will be returned 'file(2).png', and etc.
let fileList=['fa.png','fb.mp4','fc.jpeg','fa(1).png'];
const getName=(fileName)=>{
let [name,end]=fileName.split('.');
let num = 0;
let curName = `${name}.${end}`;
let exists=fileList.filter(f => f === curName).length;
while(exists) {
console.log('curName:',curName,'exists:',exists,'num:',num);
curName = `${name}(${++num}).${end}`;
exists=fileList.filter(f => f === curName).length;
}
return curName;
}
console.log(getName('fa.png'));
see in codeSandbox
I'm working on a vue.js application and i'm adding multiple file uploader with slide option. I'm using below method
<input
id="file-upload"
ref="file"
class="custom-file-input"
multiple
name="document_file"
type="file"
#change="setFile($event)"
/>
<label class="custom-file-label selected overflow-hide">{{ $t('Browse') }}</label>
data() {
return {
imageUrls: [],
img_id: 0,
currentIndex: 0
}
},
setFile(e) {
let self = this;
let reader = new FileReader();
if(e.target.files.length > 0){
for (let i = 0; i < e.target.files.length; i++) {
alert();
reader.readAsDataURL(e.target.files[i]);
reader.onload = function () {
self.imageUrls.push(
{
id: self.img_id,
file: reader.result
});
self.img_id++;
}
}
console.log('imageUrls: ', self.imageUrls);
}
},
with the alert object(all the selected files) are being pushed to array. but when i comment the alert it's giving below error
DOMException: An attempt was made to use an object that is not, or is no longer, usable
what is the reason for this?
You have to use FileReader() object for each files. try this
<input
id="file-upload"
ref="file"
class="custom-file-input"
multiple
name="document_file"
type="file"
#change="setFile"
/>
<label class="custom-file-label selected overflow-hide">{{ $t('Browse') }}</label>
data() {
return {
images: [],
imageUrls: [],
img_id: 0,
currentIndex: 0
}
},
setFile(e) {
let self = this;
var selectedFiles = e.target.files;
//let reader = new FileReader();
for (let i = 0; i < selectedFiles.length; i++) {
console.log(selectedFiles[i]);
this.images.push(selectedFiles[i]);
}
for (let i = 0; i < this.images.length; i++) {
let reader = new FileReader();
reader.onload = (e) => {
//this.$refs.image[i].src = reader.result;
// console.log(reader.result);
self.imageUrls.push(
{
id: self.img_id,
file: reader.result
});
self.img_id++;
//console.log(this.$refs.image[i].src);
};
reader.readAsDataURL(this.images[i]);
}
console.log('imageUrls: ', self.imageUrls);
},
using let reader = new FileReader(); inside the loop solve the problem
setFile(e) {
let self = this;
for (let i = 0; i < e.target.files.length; i++) {
let reader = new FileReader();
reader.readAsDataURL(e.target.files[i]);
reader.onload = function () {
self.imageUrls.push({
id: self.img_id,
file: reader.result,
});
self.img_id++;
};
}
console.log(self.imageUrls);
},
I am using tensorflowjs to do some front-end image classification. I am trying to use tf.browser.fromPixels to convert an img element to a tensor. However, I am getting all zeros of shape [160, 160, 3]. I am using the FileReader api to read an image from the file system via the <input type="file"> element. Here's some of the code:
function getFiles(event) {
const files = event.target.files;
let tempStore = [];
for (let i = 0; i < files.length; ++i) {
tempStore.push(files[i]);
}
return tempStore;
}
const imageElement = document.getElementById("upload");
imageElement.addEventListener("change", event => {
const files = getFiles(event);
Promise.all(files.map(loadImg)).then(d => {
console.log("All done !!!", d);
});
});
const loadImg = imgFile => {
return new Promise((resolve, reject) => {
let reader = new FileReader();
let imgEl = document.createElement("img");
reader.onload = async e => {
imgEl.src = e.target.result;
imgEl.setAttribute("width", 160);
imgEl.setAttribute("height", 160);
document.body.append(imgEl);
const fromPixels = tf.browser.fromPixels(imgEl);
resolve(fromPixels);
};
reader.onerror = reject;
reader.readAsDataURL(imgFile);
});
};
The image gets appended to document body properly.
The imageElement is of the form:
<img src="data:image/jpeg;base64,....." width=160 height=160>
You are creating the tensor from the image when the img tag has not yet been loaded. Here is the way to go
imgEl.src = e.target.result;
imgEl.setAttribute("width", 160);
imgEl.setAttribute("height", 160);
document.body.append(imgEl);
im.onload = () => {
// create the tensor after the image has loaded
const fromPixels = tf.browser.fromPixels(imgEl);
resolve(fromPixels);
}
I am trying to read excel file in Javascript with the plugin xlsx.js . I can read all cell values except the first value. Here is my code:
let numArr = [];
selectFile(event) {
let reader = new FileReader();
reader.onload = () => {
const data = reader.result;
const workbook = XLSX.read(data, {
type: 'binary'
});
workbook.SheetNames.forEach((sheetName) => {
// Here is your object
const XL_row_object = XLSX.utils.sheet_to_json(workbook.Sheets[sheetName]);
// var json_object = JSON.stringify(XL_row_object);
for (let i = 0; i < XL_row_object.length; i++) {
// this.groupNumsArr.push(XL_row_object[i]['number']);
const theNum = Object.values(XL_row_object[i])[0].toString();
numArr.push(theNum);
}
});
};
reader.readAsBinaryString(event.target.files[0]); }
The api gives first row as key so You can try this
for (let i = 0; i < XL_row_object.length; i++) {
var theNum = '';
if(i == 0)
{
theNum = Object.keys(XL_row_object[i])[0].toString();
numArr.push(theNum);
}
// this.groupNumsArr.push(XL_row_object[i]['number']);
theNum = Object.values(XL_row_object[i])[0].toString();
numArr.push(theNum);
}