How to add multiple images to Firebase realtime database using Vuejs? - javascript

I am trying to upload images to realtime firebase database. I made it with one images but I have no idea how to add multiple images.
This is my solution for one image.
<v-layout row>
<v-flex xs12 sm6 offset-sm3>
<!-- accept nam govori da uzme slike i nista vise-->
<v-btn raised #click="onPickFile">Upload image</v-btn>
<input
type="file"
style="display:none"
ref="fileInput"
accept="image/*"
#change="onFilePicked"/></v-flex
></v-layout>
In data I have this two: imgURL: "",
image: null
And this is a method:
onFilePicked(event) {
//files is list of imaages by puting files[0] we are taking just one
const files = event.target.files;
let filename = files[0].name;
if (filename.lastIndexOf(".") <= 0) {
return alert("Please add a valid file!");
}
const fileReader = new FileReader();
fileReader.addEventListener("load", () => {
this.imgURL = fileReader.result;
});
fileReader.readAsDataURL(files[0]);
this.image = files[0];
},

Although, this is not a firebase related question, but I try to help anyway:
First of all, you should add multiple to the input-tag, so you can select more than only one file there:
// CHANGE THIS:
<input type="file" style="display:none" ref="fileInput" accept="image/*" #change="onFilePicked"/>
// TO THIS:
<input type="file" style="display:none" ref="fileInput" accept="image/*" #change="onFilePicked" multiple/>
I assume you stumbled upon this wierd 'for-loop' for the files.. I had the same issue and figured out when I type of instead of in, then I get the file itself, not just the index and there is no error.
I splitted up the main parts of your function and converted them in asyncron Promises (because there might be a timing error with the addEventListener)
This is just the idea of the multiple files upload. Maybe you should add some more error-catcher:
new Vue({
data: {
blobs: [],
images: [],
},
methods: {
async onFilePicked(event) {
const files = event.target.files
this.images =[]
this.blobs =[]
for (let file of files) {
this.images.push(file)
let blob = await this.prepareImagesForUpload(file)
this.blobs.push(blob)
}
this.uploadImagesToFirebase()
},
prepareImagesForUpload(file) {
return new Promise((resolve, reject) => {
let filename = file.name
if (filename.lastIndexOf(".") <= 0) {
alert("Please add a valid file: ", filename)
reject()
}
const fileReader = new FileReader()
fileReader.readAsDataURL(file)
fileReader.addEventListener("load", async () => {resolve(fileReader.result)})
})
},
uploadImagesToFirebase() {
//... do the firebase upload magic with:
console.log(this.blobs)
//...
}
}
})

Related

Image uploading in Angular

I was trying to upload an image using Angular to a google storage bucket. And everything is working fine with Postman.
But I'm stuck with angular typescript. Can anyone suggest to me a way to do this?
.html file
<input type="file" accept="image/png, image/jpeg" class="form-control upload-btn" formControlName="imageUpload" placeholder="Upload Images" (change)="uploadImage($event)" required>
.ts file
uploadImage(event: any) {
if (event.target.files && event.target.files[0]) {
const uploadImage=event.target.files[0];
const fileObject = {
userId: this.userId,
bucketName: 'Test123',
image: uploadImage
};
this.userService.uploadImage(fileObject).subscribe(data=>{
},err=>{
console.log("error occured")
}
)
}
}
.service file
uploadImage(fileObject: any){
return this.http.post('http://localhost:1337' + 'upload-image' , fileObject);
}
No any error occurs on the backend side. It worked fine with Postman.
Im not sure about the .ts file.
As suggested by #PrasenjeetSymon using FormData will help to upload images in Angular.
Here is the similar thread which demonstrate how to use FormData
You can use the tag from HTML:
<input type="file" name="file" id="file" (change)="onFileChanged($event)" />
and in the component:
public files: any[];
contructor() { this.files = []; }
onFileChanged(event: any) {
this.files = event.target.files;
}
onUpload() {
const formData = new FormData();
for (const file of this.files) {
formData.append(name, file, file.name);
}
this.http.post('url', formData).subscribe(x => ....);
}

Get input file path using NeutralinoJS

How do I get input file path using NeutralinoJS?
My Code:
<input type="file" id="inputFile">
const inputFilePath = document.getElementById('inputFile').files[0].path
console.log(inputFilePath)
I don't think browsers allow you to get file paths.
You could use the file picker API instead os.showDialogOpen(DialogOpenOptions):
https://neutralino.js.org/docs/api/os#osshowdialogopendialogopenoptions
<button onclick="onFileUpload()">
async onFileUpload () {
let response = await Neutralino.os.showDialogOpen({
title: 'Select a file'
})
console.log(`You've selected: ${response.selectedEntry}`)
}
Why do you need the path? If you need the content from the upload file you can get it via javascript filereader API and use the contents.
If you need the file for later use you can read the file via js filereader and then create and save a new file with filesystem.writeFile(WriteFileOptions) to your prefered location (maybe app internal temp path). Be sure the destination path exists. For that you can use filesystem.createDirectory(CreateDirectoryOptions).
Example with jQuery:
jQuery(document).on('change','#myUpload',function(){ //Click on file input
if(jQuery(this).val().length > 0){ //Check if a file was chosen
let input_file = this.files[0];
let file_name = input_file.name;
let fr = new FileReader();
fr.onload = function(e) {
fileCont = e.target.result;
//Do something with file content
saveMyFile(file_name, fileCont); //execute async function to save file
};
fr.readAsText(input_file);
}
});
async function saveMyFile(myFileName, myFileContent){
await Neutralino.filesystem.createDirectory({ path: './myDestPath' }).then(data => { console.log("Path created."); },() => { console.log("Path already exists."); }); //create path if it does not exist
//write the file:
await Neutralino.filesystem.writeFile({
fileName: './myDestPath/' + myFileName,
data: myFileContent
});
}
You can use the Neutralino.os API for showing the Open/Save File Dialogs.
This is A Example For Opening A File.
HTML:
<button type="button" id="inputFile">Open File</button>
JavaScript:
document.getElementById("inputFile").addEventListener("click", openFile);
async function openFile() {
let entries = await Neutralino.os.showOpenDialog('Save your diagram', {
filters: [
{name: 'Images', extensions: ['jpg', 'png']},
{name: 'All files', extensions: ['*']}
]
});
console.log('You have selected:', entries);
}

How to add multiple files by drag n drop also by click with upload progress bar

I have to build a custom upload with multiple file upload support with progress bar, I have done the design part. Only thing I cant find is multiple file upload with drag n drop and progress bar. Please help I have attached the progress sample image.
<div>
<input type="file" id="file" multiple
(change)="getFileDetails($event)">
</div>
<div *ngFor="let file of myFiles">
<div>{{file.name}} - {{file.type}} - {{file.size}}</div>
</div>
myFiles:string [] = [];
sMsg:string = '';
ngOnInit () { }
getFileDetails (e) {
//console.log (e.target.files);
for (var i = 0; i < e.target.files.length; i++) {
this.myFiles.push(e.target.files[i]);
}
console.log(this.myFiles)
}
stackblitz
I use ng2-file-upload. It's pretty clean and allows for progress bars, automatic uploads, drag and drop, custom upload headers.
https://github.com/valor-software/ng2-file-upload
simplified example from my codebase
const authHeader = { name: "authCode", value: this.sessionService.GetAuthCode() }; //authorization token
this.uploader = new FileUploader({
headers: [authHeader],
url: <path-to-api-service>,
parametersBeforeFiles: true,
autoUpload: true
});
this.uploader.onCompleteAll = () => {
//reload available files
};
this.uploader.onCompleteItem = (item: FileItem, response: string, status: number, headers: ParsedResponseHeaders) => {
console.log("file completed", item, status, response, headers);
};

filepond post image with metadata

i'm writing a upload page using filepond. The problem i'm facing is to get it to work like i want. I need to get the metadata from the input and post it with additional formdata
I can allready post the image and additional formdata. However I also want the metadata from the input. If I use onaddfile and log the metadata it works and shows additional="1"
<input type="file" id="img" name="img" data-file-metadata-additional="1">
pond=FilePond.create(document.querySelector('#img'),{
server: {
process: {
url: 'opbouw/model/post/addimg.php',
ondata: (formData) => {
// > POST META DATA
formData.append('userid', '2');
formData.append('usercom', '1');
return formData;
}
}
},
});
pond.onaddfile = (err, item) => {
console.log(item);
const metadata = item.getMetadata();
console.log(metadata);
}
So no clue how to post the metadata
If you're not going to write a custom server.process method then you're going to have to "remember" which metadata belongs to which file.
Something like this:
<input type="file" id="img" name="img" data-file-metadata-additional="1">
<script>
let pondMetadata;
const pond = FilePond.create(document.querySelector('#img'), {
server: {
process: {
url: 'opbouw/model/post/addimg.php',
ondata: (formData) => {
// add metadata
formData.append('usermeta', JSON.stringify(pondMetadata));
formData.append('userid', '2');
formData.append('usercom', '1');
return formData;
}
}
},
onaddfile: (err, item) => {
pondMetadata = item.getMetadata();
}
});
</script>

Axios for Vue not uploading image to server

When I want to upload an image and send the other data using FormData. Axios seems to serialize the image. Therefore, when i upload the image using Axios, the image is inside the body's payload as a string. As a result, I'm unable to use Multer on the server side to retrieve the uploaded image from the request.
This is my Vue code:
export default () {
name: 'app',
data () {
image: ''
},
methods: {
onFileChange (e) {
var files = e.target.files || e.dataTransfer.files
if (!files.length) {
return
}
// console.log(files[0])
// var x = files[0]
return this.createImage(files[0])
// return new Buffer(x)
},
createImage (file) {
// var image = new Image()
var reader = new FileReader()
var vm = this
reader.onload = (e) => {
// vm.image = e.target.result
vm.image = file.toString('base64')
console.log(vm.image)
}
reader.readAsDataURL(file)
},
submitStaff () {
const formData = new FormData()
formData.append('file', this.image)
formData.append('name', this.data.name)
formData.append('username', this.data.username)
formData.append('password', this.data.password)
axios.post('api/myApiUrl', formData)
.then(function (response) {
console.log(response)
})
.catch(function (error) {
console.log(error)
})
}
}
<input type="file" #change="onFileChange">
Request Payload (Error with Vue)
Request Payload (Successful with Postman)
How do i fix this? Thank you!
I faced a problem related to it and in my case I was setting Content-Type as a default configuration for all my requests, doing this:
axios.defaults.headers.common['Content-Type'] = 'application/json [or something]';
And, as I remember, part of my solution was to remove this configuration to make the upload works. I just erased that line from my code and all requests worked well. As soon I removed it, I could notice that my headers request changed to this (see attached image and notice the Content-Type entry):
Another thing you should be alert is the field name to your <input type="file" name="file">. I have a java backend expecting a parameter named as "file", so, in my case, my input file HAS to be set as "file" on my HTML and on my server side, like this:
public ResponseEntity<Show> create(
#RequestParam("file") MultipartFile file,
RedirectAttributes redirectAttributes) { ... }
Observe the entry #RequestParam("file")...
And in the HTML file:
<form enctype="multipart/form-data" novalidate v-if="isInitial || isSaving">
<div class="well">
<div class="form-group">
<label>* Selecione o arquivo excel. O sistema fará o upload automaticamente!</label>
<div class="dropbox">
<input type="file" single name="file" :disabled="isSaving" #change="filesChange($event.target.name, $event.target.files); fileCount = $event.target.files.length"
accept="application/vnd.ms-excel" class="input-file">
<p v-if="isInitial">
Solte o arquivo excel aqui<br> ou clique para buscar.
</p>
<p v-if="isSaving">
Carregando arquivo...
</p>
</div>
</div>
</div>
</form>
You also can take a look at this tutorial, it my help you: https://scotch.io/tutorials/how-to-handle-file-uploads-in-vue-2
I hope it helps you!

Categories

Resources