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>
Related
I have one API call where I provide image and other key values.
Everything works fine when I do it with POSTMAN. I select formData and add an image along with other key values.
But when I do the same in Angular it does not work.
every field get stored in the table except the image part.
My angular code is below
onFileSelected(event) {
this.selectedFile = <File>event.target.files[0];
}
create(){
var data ={};
const fd = new FormData();
fd.append('image',this.selectedFile,this.selectedFile.name);
Object.keys(this.productForm.controls).forEach(key => {
data[key] = this.productForm.get(key).value;
});
data["image"] = fd;
this.spinner.show();
this._service.post(Constant.createProduct,data).subscribe(res=>{
console.log(res);
this.spinner.hide();
},
error=>{
this.spinner.hide();
});
}
I have also added a screenshot of the postman body which is working but not angular code.
This is backend service code in Laravel.
public function createProduct(Request $req){
// 'name', 'preferred_chamber' ,'profile_picture_1','profile_picture_2','address', 'zone','note','google_location', 'list_number', 'phone_number', 'phone_number_2'
$p=new Product();
$p->name=$req->name;
$p->brand_name=$req->brand_name;
$p->mrp=$req->mrp;
$p->cost_price=$req->cost_price;
$p->unit=$req->unit;
$p->weight=$req->weight;
$p->qty=$req->qty;
$p->inventory_qty=$req->inventory_qty;
$p->category=$req->category;
$p->reorder_qty=$req->reorder_qty;
$p->product_desc=$req->product_desc;
$p->inventory_type=$req->inventory_type;
//upload profile picture
if ($req->hasFile('image')) {
$pp1_name=time().".jpg";
$pp1 = request()->file('image')->move("/home/u481243053/domains/freelanceglobal.tech/public_html/sk_uploads", $pp1_name);
$p->image= "http://freelanceglobal.tech/sk_uploads/".$pp1_name;
}
$p->save();
return response()->json(['product'=>$p]);
}
When you have an image then you shoud send FormData to request.
create(){
const fd = new FormData();
fd.append('image',this.selectedFile,this.selectedFile.name);
Object.keys(this.productForm.controls).forEach(key => {
fd.append(key,this.productForm.get(key).value);
});
this.spinner.show();
this._service.post(Constant.createProduct,fd).subscribe(res=>{
console.log(res);
this.spinner.hide();
},
error=>{
this.spinner.hide();
});
}
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)
//...
}
}
})
When creating an event, I also upload an image to Firebase Storage.
Then I create an array this.eventz to display the events on the home page. For each event I want to retrieve the image as well, but I get a Firebse error:
FirebaseStorageError {code_: "storage/object-not-found", message_: "Firebase Storage: Object 'events/-KxCuUuss1I2uFolk99m/-KxCuUuss1I2uFolk99m_main.png' does not exist.", serverResponse_: "{↵ "error": {↵ "code": 404,↵ "message": "Not Found. Could not get object"↵ }↵}", name_: "FirebaseError"}
I understand that the image isn't uploaded yet when I want to include it in the array but I don't know how to fix my problem. The code works fine. It displays all the events, adds images to each one ... it's just that error when creating a new event.
getEventImage(event) {
if (event) {
const mainPhotoRef = firebase.storage().ref('events');
console.log(mainPhotoRef);
mainPhotoRef.child(`/${event.key}/${event.key}_main.png`).getDownloadURL()
.then(url => this.makeEvents(url, event))
}
}
makeEvents(url, event) {
console.log(url);
if (url) {
try {
event.img = url;
let index = _.findIndex(this.eventz, ['key', event.key]);
if (index >= 0) {
this.eventz.splice(index, 1);
}
this.eventz.push(event);
} catch (err) {
console.log(err);
}
}
}
I fixed my problem by saving the url to the event object when creating it. I would like to know if I am uploading correctly.
private uploadPhoto(itemKey): void {
this.myPhotosRef.child(itemKey).child(`${itemKey}_main.png`)
.putString(this.myPhoto, 'base64', { contentType: 'image/png' })
.then((savedPicture) => this.updateEventImage(savedPicture.downloadURL, itemKey));
}
updateEventImage(url, itemKey) {
console.log(url);
const newEvent = this.db.object(`events/${itemKey}`)
newEvent.update({ eventImage: url });
}
I am trying to upload a file to the server with vuejs, actually i don't want the form to treat the file and upload it, i prevent the submit and treat some logic by myself, so at the begin i want to do something simple just check if it is a pdf and if everything is ok it should point to /upload in the localhost defined for NodeJS server
<template>
<div id="app">
<form>
<h2>Select a file</h2>
<input id="inputVal" type="file" #change="onFileChange">
<button #click.prevent="sendFile()">Send</button>
</form>
</div>
</template>
<!-- Javascript -->
<script>
export default {
name: 'app',
data() {
return {
file: ''
}
},
methods: {
onFileChange(e) {
var files = e.target.files || e.dataTransfer.files;
if (!files.length) {
return;
}
var ext = files[0].name.split('.').pop();
if(ext === 'pdf') {
this.createFile(files[0]);
}
else {
this.file = '';
this.clearFileInput(document.getElementById('inputVal'));
}
},
createFile(file) {
this.file = file;
},
clearFileInput(ctrl) {
try {
ctrl.value = null;
} catch(ex) { }
if (ctrl.value) {
ctrl.parentNode.replaceChild(ctrl.cloneNode(true), ctrl);
}
},
sendFile() {
var vm = this;
if(this.file !== '') {
this.$http.post('http://localhost:3000/upload',{params: vm.file, headers: {'Content-Type': 'multipart/form-data'}})
.then(response => {
// JSON responses are automatically parsed.
//
}, error => {
//this.errors.push(e)
});
}
}
}
}
</script>
on my server side i am receiving undefined, i don't really know why, i just wanna see if i really got any file in the server, and if yes i want to save it on the server side, any help with that?
i just did this on the /upload endpoint:
router.post('/upload',function(req,res) {
console.log(res.body);
})
You will get Files object from input which is not the actual file but a special reference to a file, you need to useFileReader or FormData to get the actual file and send it, try something like this
var data = new FormData();
var pdf = e.target.files[0];
data.append('file',pdf)
this.$http.post('http://localhost:3000/upload',{params: data}, headers: {'Content-Type': 'multipart/form-data'}})
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!