anyone knows how to submit file with bootstrapVue file input?
I am getting null from request->all()
array:13 [
...
"calibration_cert" => array:1 [
"$path" => null
]
]
Below is what I tried
<b-form-group label="Calibration Cert:">
<b-form-file
v-model="form.calibration_cert"
:state="Boolean(form.calibration_cert)"
placeholder="Choose a file or drop it here..."
drop-placeholder="Drop file here..."
></b-form-file>
</b-form-group>
.....
methods:{
onSubmit(event) {
event.preventDefault();
axios
.post("/equipments/create", this.form, {
headers: {
"Content-Type": "multipart/form-data"
}
})
.then(response => {
console.log(response);
})
};
},
Appreciate if anyone can help
Your lucky day, I'm just working on this.
You have to use formData() object for submitting files from Axios.
If your Laravel route uses a patch method, you have to use axios.post() instead of axios.patch() and append the _method: PATCH in your formData
Saying that, this is how I do it:
component.vue
<b-form-file
v-model="form.calibration_cert"
:state="Boolean(form.calibration_cert)"
placeholder="Choose a file or drop it here..."
drop-placeholder="Drop file here..."
></b-form-file>
.....
methods:{
onSubmit(event) {
event.preventDefault();
// Set formData
const formData = new FormData()
// Append the method only if you are using a patch route in your server side
formData.append('_method', 'PATCH')
// Append the file
formData.append('calibration_cert', this.form.calibration_cert)
// Append the rest of your form data
formData.append('data1', this.form.data1)
formData.append('data2', this.form.data2)
.....
axios
.post("/equipments/create", formData, {
headers: {
"Content-Type": "multipart/form-data"
}
})
.then(response => {
console.log(response);
})
};
},
Then in your Laravel side, you can do
$path = $request->file('calibration_cert')->store('files');
You need to send the files as a object in axios request, use below example to understand what you should do.
const app = new Vue({
data: () => ({images: null}),
template: `
<div>
<input type="file" #change="uploadFile" ref="file">
<button #click="submitFile">Upload!</button>
</div>
`,
methods: {
uploadFile() {
this.Images = this.$refs.file.files[0];
},
submitFile() {
const formData = new FormData();
formData.append('file', this.Images);
const headers = { 'Content-Type': 'multipart/form-data' };
axios.post('https://httpbin.org/post', formData, { headers }).then((res) => {
res.data.files; // binary representation of the file
res.status; // HTTP status
});
}
}
});
app.$mount("#content");
Related
According to the documentation server configuration for load should return a file object with header Content-Disposition, but what does file object means? How does it looks like?
With my code below I can load the image name correctly only, I need to load preview image and file size also.
Javascript
<script>
FilePond.registerPlugin(FilePondPluginFileValidateType);
FilePond.registerPlugin(FilePondPluginFileValidateSize);
FilePond.registerPlugin(FilePondPluginImagePreview);
FilePond.registerPlugin(FilePondPluginFilePoster);
FilePond.setOptions({
server: {
process: '/upload',
revert: '/remove',
load: '/load/?serverId=',
headers: {
'X-CSRF-TOKEN': '{{ csrf_token() }}'
}
}
});
const inputElement = document.querySelector('#filepond');
const pond = FilePond.create(inputElement, {
files: [
#foreach ($productItem->galleries as $gallery)
{
source: '{{ $gallery->id }}',
options: {
type: 'local',
}
},
#endforeach
],
acceptedFileTypes: ['image/*'],
maxFileSize: '5MB',
onremovefile: (error, file) => {
if (error) {
console.log('Oh no');
return;
}
console.log('File removed', file.getMetadata('serverId'));
}
})
</script>
PHP
public function load(Request $request) {
$file = FileItem::find($request->serverId);
return response()
->json($file->path, 200, [
'Content-Disposition' => "inline; filename='$file->filename'",
]);
}
I see you are using Laravel, instead of handling filepond from scratch. I recommend you to use https://github.com/rahulhaque/laravel-filepond
Easy to use, and if you want to load an initial image or file. you just need a little customization. here is how I handle it.
FilePond.registerPlugin(
FilePondPluginFileValidateType,
FilePondPluginImagePreview,
);
// this is the url of image.
let url = `{{ $slider->getFirstMedia('sliders')->getUrl() }}`;
FilePond.setOptions({
server: {
url: "{{ config('filepond.server.url') }}",
headers: {
'X-CSRF-TOKEN': "{{ #csrf_token() }}",
},
load: (source, load, error, progress, abort, headers) => {
// now load it using XMLHttpRequest as a blob then load it.
let request = new XMLHttpRequest();
request.open('GET', source);
request.responseType = "blob";
request.onreadystatechange = () => request.readyState === 4 && load(request.response);
request.send();
},
}
});
// don't forget to set options local to tell filepond this is already uploaded
// parameter sourse ask for url.
FilePond.create(document.querySelector('#cover'), {
acceptedFileTypes: ['image/png', 'image/jpeg'],
files: [{
source: url,
options: {type: 'local'},
}],
});
Filepond
I have a problem with file uploading on my Laravel&Vue.js website using API
I get - 500 Server Error "SyntaxError: Unexpected token < in JSON at position 0"
I'm trying to create new value in my database, for this I use pop up form with image uploading and other fields like username, email, phone etc.
I've tested my API via Postman - it works fine, but when I try to create this directly on my website - it desn't work
you can check a function which must create new value(startup) in DB:
createStartup() {
fetch('/api/startup', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'multipart/form-data'
},
body: JSON.stringify(this.new_startup),
})
.then(res => res.json())
.then(res => {
$('#createStartUp').modal('hide');
alert('New Startup Created!');
// this.fetchStartups();
})
.catch(err => console.log(err));
}
I think the issue in Headers (I didn't use any Headers in Postman), when I tried to not use any Headers - it didn't wok too, also O tried to use Content-Type with bypass and unfortunately it didn't work
Also I think it must be helpful - how I get image in vue.js:
HTML:
<input id="upload_create" class="file-upload_input" type="file" #change="onFileSelected" >
JS (Vue.js):
onFileSelected(event) {
this.new_startup.startup_logo = event.target.files[0];
}
Thanks a lot guys for any ideas and helps!
You need to pass your data as form-data. Here is how I managed to send a file upload via Vue.js:
createStartup() {
let formData = new FormData();
formData.append('file', this.new_startup.startup_logo);
formData.append('anythingElse', JSON.stringify(this.someVariable);
// ... etc
fetch('/api/startup', {
method: 'POST',
headers: {
'Content-Type': 'multipart/form-data'
},
body: formData,
})
.then(res => res.json())
.then(res => {
$('#createStartUp').modal('hide');
alert('New Startup Created!');
// this.fetchStartups();
})
.catch(err => console.log(err));
}
My ajax axios like this :
let formData = new FormData()
formData.append('file', user.avatar)
formData.append('selected_data', JSON.stringify(user))
axios.post('/member/profile/update',
formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
}
)
.then(response => cb(response))
.catch(error => ecb(error))
My routes like this :
Route::post('update', 'member\UserController#update')->name('member.profile.update');
If the script executed, it works. I success get the data sended
But here, I want to change post method to put method. Because this used to update profile
I change like this :
axios.put(...
And the routes :
Route::put('update', ...
I don't success get the data sended. The data sended is empty
How can I solve this problem?
Update :
If I console.log(user), the result like this :
Laravel uses method spoofing for PUT, use axios.post and add the following to your requests data:
data: {
...
_method: 'PUT',
...
}
You can do:
formData.append('_method', 'PUT')
Complete example using axios:
axios.post('/user', { _method: 'PUT', foo: 'bar' })
.then(function (response) { console.log(response); })
.catch(function (error) { console.log(error); });
Form method spoofing
My vue component to upload file image like this :
<template>
<section>
<ul class="media-list">
...
</ul>
</section>
</template>
<script>
export default {
...
props: ['productId'],
methods: {
...
onFileChange(e, index) {
let files = e.target.files,
let formData = new FormData()
formData.append('file', files[0])
axios.post(window.App.baseUrl+'/admin/product/upload-image',
formData,
{
headers: {
'Content-Type': 'multipart/form-data'
}
}
).then(function(){
console.log('SUCCESS!!')
})
.catch(function(){
console.log('FAILURE!!')
});
}
}
}
</script>
So it will call onFileChange method if user upload file image
My routes like this :
Route::prefix('admin')->group(function(){
Route::prefix('product')->group(function(){
Route::post('upload-image', 'Admin\ProductController#uploadImage')->name('admin.product.upload-image');
});
});
My controller like this :
public function uploadImage(Request $request)
{
echo '<pre>';print_r($request->all());echo '</pre>';die();
}
The code works. I success get file uploaded in the controller
But here I want to pass another paramater too. I want to pass parameter productId
I try change code axios like this :
...
axios.post(window.App.baseUrl+'/admin/product/upload-image',
{product_id: this.productId, formData}
...
It does not work. The result is empty
How can I solve this problem?
Put product_id in formData.
let formData = new FormData();
formData.append('file', files[0]);
formData.append('product_id', this.productId);
axios.post(window.App.baseUrl+'/admin/product/upload-image', formData)
.then(function(){
console.log('SUCCESS!!')
})
.catch(function(){
console.log('FAILURE!!')
});
I want to send a post request to Laravel backend using Vue.js. I'd like to make it without any extra library. I am making a pure Vue.http.get request and it works like a charm. For testing Laravel route and Controller returned data, I've made a ajax request in my template, which also works fine, returning the correct data. However, when I use Vue, via Vue.http.post('My/Controller/Route',data) it doesn't sends the post data to the Controller.
My Vue.js component:
<template>
<div class="opt-pro" v-for="r in profissionais">
<input :id="r.id" type="checkbox" :value="r.id" v-model="checkedNames" v-on:change="filterResources()"/><label> {{ r.title }}</label>
</div>
</template>
<script>
export default {
data() {
return {
dados: {view: 'dia', pro: [], data: 'Setembro 11, 2017'},
meus_recursos: [],
profissionais: [],
checkedNames: []
}
},
methods:{
getResources: function() {
var self = this;
return Vue.http.get('/admin/getResources').then((response) => {
_.forEach(response.data.resources,function(item){
self.meus_recursos.push(item);
self.profissionais.push(item);
});
console.log(self.meus_recursos);
});
},
filterResources: function(){
this.dados.pro = this.checkedNames; // returned by another Vue piece of code - console.log() returns the correct data for this var
return Vue.http.post('/admin/getAgendamentosPorProfissional', this.dados).then(
(response) => {
console.log(response.body);
},
(response) => {
console.log("Error");
console.log(response);
console.log(response.body);
});
}
}
My Laravel Controller function:
public function getAgendamentosPorProfissional(){
// $view = $_POST['view'];
// $pro = $_POST['pro'];
// $data = $_POST['data'];
$post = $_POST;
return response()->json(array('post' => $post),200);
}
It returns in my console:
{post: Array(0)}
My jQuery AJAX function:
$.ajax({
type:'POST',
url:'/admin/getAgendamentosPorProfissional',
data: {"data": data, "view": view, "pro": [pro],"_token": "{{ csrf_token() }}"},
success:function(data){
console.log("AJAX - /admin/getAgendamentosPorProfissional");
console.log(data);
}
});
It returns in my console:
post:
data: "Setembro 11, 2017",
pro:["75"]
view:"dia"
_token:"6LviacS2KoBqjXxTsFhnTtAQePuEzZ49OMwqBmbM"
It's not a CORS issue, since it returns the correct data from the requested url in laravel. How can I fix this?
My token is set at laravel/resources/assets/js/bootstrap.js file:
window.Vue = require('vue');
require('vue-resource');
Vue.http.interceptors.push((request, next) => {
request.headers.set('X-CSRF-TOKEN', Laravel.csrfToken);
next();
});