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
Related
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");
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();
});
When I fill search box, auto-completion doesn't work correctly. My query doesn't work.
Below is my html code:
$(document).ready(function(){
$('#keyword').autocomplete({
source: function( request, response ) {
$.ajax({
url : '/search',
dataType: "json",
data: {
username: request.term
},
success: function( data ) {
response( $.map( data, function( item ) {
return {
id: '<B>' + item.id + '</B>',
value: item.value
}
}));
}
});
},
autoFocus: true,
minLength: 2,
select: function(event, ui) {
var url = ui.item.id;
if(url != '#') {
location.href = '/admin/users/' + url+ '/edit';
}
},
html: true,
open: function(event, ui) {
$(".ui-autocomplete").css("z-index", 1000);
}
});
});
<input name="keyword" id="keyword" class="form-control txt-auto"/>
my function
public function search(Request $request) {
$keyword = $request->input('keyword');
$results = array();
$user = User::where('username', 'LIKE','%'.$keyword.'%')->get();
foreach ($user as $query)
{
$results[] = [ 'id' => $query->id, 'value' => $query->username ];
}
return Response::json($results);
}
Route::get( '/search' , 'ShopController#search' );
I know i'm late to the party but I had this exact issue.
The z-index needs to be added while loading of your html:
What I did was I added this to one of my css files:
.ui-autocomplete {
z-index:2147483647;
}
After that, the autocomplete started working.
I haven't used autocomplete in a while, but I see two problems in your code. First, according to the docs
The Autocomplete plugin does not filter the results, instead a query string is added with a term field, which the server-side script should use for filtering the results. For example, if the source option is set to "http://example.com" and the user types foo, a GET request would be made to http://example.com?term=foo. The data itself can be in the same format as the local data described above.
Yet, you are using:
$keyword = $request->input('keyword');
instead of
$term = $request->input('term');
Second, maybe you need an ajax call inside the source option for something in particular, but you can simply do:
$('#keyword').autocomplete({
source: "/search",
select: function(event, ui) {
// ... do something here. Try logging the output
console.log(ui.item);
}
});
I read this: https://github.com/enyo/dropzone/wiki/Set-URL-dynamically but i dont got success... :(
I have 1 form...
And i send the inputs with ajax.
The ajax returns the new id of user. in this moment i want to change de url dropzone for to set path to id of the new user.
$.ajax({
type: "POST",
url: "class/inserir.php?funcao=teste",
data: formdata,
dataType: "json",
success: function(json){
if(json.sucesso=="sim"){
alert("Wait! Sending Pictures.");
this.options.url = "class/upload_img.php?"+json.id;
myDropzone.processQueue();
}else{
location.href="home.php?ir=cad_animal&cad=nao&erro="+json.erro;
}
}
});
var myDropzone = new Dropzone("#imagens", {
url: "class/upload_imgteste.php",
paramName: "file", // The name that will be used to transfer the file
maxFilesize: 1, // MB
addRemoveLinks : true,
dictResponseError: "Não foi possível enviar o arquivo!",
autoProcessQueue: false,
thumbnailWidth: 138,
thumbnailHeight: 120,
});
sorry for my bad english!
Thanks for all.
You may add a function on dropzone's "processing" event listener.
Dropzone.options.myDropzone = {
init: function() {
this.on("processing", function(file) {
this.options.url = "/some-other-url";
});
}
};
Here is the link where I got the code and it works for me: https://github.com/enyo/dropzone/wiki/Set-URL-dynamically
change this
this.options.url = "class/upload_img.php?"+json.id;
to this
myDropzone.options.url = "class/upload_img.php?"+json.id;
Does that work?
New answer for an old question only because I found this answer and the link to the dropzone wiki and didn't like it. Modifying the options of the plugin multiple times like that seems very wrong.
When dropzone uses some options it runs it through a resolveOption function passing in a files array. In the current branch you can define a function for the options: method, url and timeout.
Here's a complete working example including delaying for the ajax:
Dropzone.autoDiscover = false;
const doStuffAsync = (file, done) => {
fetch('https://httpbin.org/get').then((response) => {
file.dynamicUploadUrl = `https://This-URL-will-be-different-for-every-file${Math.random()}`
done();//call the dropzone done
})
}
const getMeSomeUrl = (files) => {
return `${files[0].dynamicUploadUrl}?sugar&spice`;
}
let myDropzone = new Dropzone("#my-awesome-dropzone", {
method: "put",
accept: doStuffAsync,
url: getMeSomeUrl
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.4.0/min/dropzone.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.4.0/min/dropzone.min.css">
<form action="/file-upload" class="dropzone" id="my-awesome-dropzone">
</form>
If you need to change the URL dropzone posts to dynamically for each file, you can use the processingfile event and change the options.url.
<form id="my-dropzone" action="/some-url" class="dropzone"></form>
<script>
Dropzone.options.myDropzone = {
init: function() {
this.on("processing", function(file) {
this.options.url = "/some-other-url";
});
}
};
</script>
Another way that worked for me (accept event callback):
$('div#dropzone').dropzone({
options...,
accept: function (file, done) {
this.options.url = 'the url you want';
}
});
BlueWater86's answer didn't work for me. But I agree that changing myDropzone.options.url each time is bad practice, and it actually doesn't work if you are dragging a lot of files into the uploader at the same time.
I wrote the following code and it works well for uploading one file at time and for many at a time. I'm using Backblaze B2 but it should also work for S3.
myDropzone.on('addedfile', function(file) {
options = {
filename: file.name,
type: file.type,
_: Date.now()
};
// Make the request for the presigned Backblaze B2 information, then attach it
$.ajax({
url: '/presign_b2',
data: options,
type: 'GET',
success: function(response){
file.dynamicUrl = response['url'];
myDropzone.enqueueFile(file);
}
});
});
myDropzone.on('sending', function(file, xhr) {
xhr.open("PUT", file.dynamicUrl); // update the URL of the request here
var _send = xhr.send;
xhr.send = function() {
_send.call(xhr, file);
}
});
The problem is very simple: i have to download a file when i submit a form, it's an ajax call when the form is submitted which lets me build a file with the data taken from the form, server side, and then send it as a link to an alert. The fact is that my boss want the file to be downloaded directly and not through a link in an alert. So i had to make sure that the file is available server side through tornado(web):
self.set_header('Content-Type', 'application/octet-stream')
self.set_header('Content-Disposition', 'attachment; filename=clients_counter.zip')
with open("static/clients_counter.zip", 'r') as f:
while True:
data = f.read()
if not data:
break
self.write(data)
self.finish()
The server side code seems to work fine, but the client side (extjs4.1) is really a nightmare. This is how my ajax call looks like now, and it doesn't work:
Ext.Ajax.request({
method : "GET",
url : 'http://whatever.com/count?client='+client+'&start='+start+'&end='+end,
timeout : 30000,
success :
function (response) {
//Ext.Msg.alert(response.responseText);
desktop.getWindow('count-win').doClose();
return response;
}//handler,
failure :
function(response) {
alert("Wrong request");
}});
After reading on various sources from Ext JS forum and here in stackoverflow, below is the approach I've chosen (using Ext JS version 4.2.1):
downloadFile: function(config){
config = config || {};
var url = config.url,
method = config.method || 'POST',// Either GET or POST. Default is POST.
params = config.params || {};
// Create form panel. It contains a basic form that we need for the file download.
var form = Ext.create('Ext.form.Panel', {
standardSubmit: true,
url: url,
method: method
});
// Call the submit to begin the file download.
form.submit({
target: '_blank', // Avoids leaving the page.
params: params
});
// Clean-up the form after 100 milliseconds.
// Once the submit is called, the browser does not care anymore with the form object.
Ext.defer(function(){
form.close();
}, 100);
}
I had a similar problem trying to download an Excel File in an Ajax call I solved it this way:
Make a standard sumbit instead of Ajax.
var form = Ext.create('Ext.form.Panel', { // this wolud be your form
standardSubmit: true, // this is the important part
url: '../ObtenerArchivoAdjuntoServlet'
});
form.submit({
params: {
nombreArchivo: nombreArchivo
}
});
After this you would be able return the desired file.
After extracting/reading many posts, I managed to get this simple method to work..
Ext.create('Ext.form.Panel', {
renderTo: Ext.getBody(),
standardSubmit: true,
url: 'URL'
}).submit({params: {'PARAM1': param1, 'PARAM2': param2}});
I think you can take a much easier solution. Forget about the ajax, and just get plain old js to open the file for you:
window.open('http://whatever.com/count?client='+client+'&start='+start+'&end='+end)
This will open a new tab and start the download from there.
The following code used to download the file using extjs 5 or 6. Add the following code to method and invoke this for button action. This downloads the file directly insteadof opening in new tab.
use an iframe like this:
/**
* prints the file
*/
printReport: function () {
var url = 'downloadURL';
Ext.Ajax.request({
url: url,
method: 'GET',
autoAbort: false,
success: function(result) {
if(result.status == 204) {
Ext.Msg.alert('Empty Report', 'There is no data');
} else if(result.status == 200) {
Ext.DomHelper.append(Ext.getBody(), {
tag: 'iframe',
frameBorder: 0,
width: 0,
height: 0,
css: 'display:none;visibility:hidden;height:0px;',
src: url
});
}
},
failure: function() {
//failure here will automatically
//log the user out as it should
}
});
}
Copied the answer from extjs forum
Option:2
If you want to open the file in new tab
/**
* open file in tab
*/
openReport: function () {
var url = 'downloadURL';
Ext.Ajax.request({
url: url,
method: 'GET',
autoAbort: false,
success: function(result) {
if(result.status == 204) {
Ext.Msg.alert('Empty Report', 'There is no data');
} else if(result.status == 200) {
var win = window.open('', '_blank');
win.location = url;
win.focus();
}
},
failure: function() {
//failure here will automatically
//log the user out as it should
}
});
}
You cannot use ajax to download file. I've implemented file downloading in extjs which is like ajax. see the blog ajaxlikefiledownload.
FileDownload.downloadFile = function(arguments) {
var url = arguments['url'];
var params = arguments['params'];
var successCallback = arguments['success'];
var failureCallback = arguments['failure'];
var body = Ext.getBody();
var frame = body.createChild({
tag:'iframe',
cls:'x-hidden',
id:'hiddenframe-frame',
name:'iframe'
});
var form = body.createChild({
tag:'form',
cls:'x-hidden',
id:'hiddenform-form',
action: url,
method: 'POST',
target:'iframe'
});
if (params) {
for (var paramName in params) {
form.createChild({
tag:'input',
cls:'x-hidden',
id:'hiddenform-'+paramName,
type: 'text',
text: params[paramName],
target:'iframe',
value: params[paramName],
name: paramName
});
}
}
form.dom.submit();
FileDownload.isFinished(successCallback,failureCallback);
};
FileDownload.isFinished = function(successCallback,failureCallback) {
//Check if file is started downloading
if (Ext.util.Cookies.get('fileDownload') && Ext.util.Cookies.get('fileDownload')=='true' ) {
//Remove cookie call success callback
Ext.util.Cookies.set('fileDownload', null, new Date("January 1, 1970"),application.contextPath+'/');
Ext.util.Cookies.clear('fileDownload',application.contextPath+'/');
successCallback();
return;
}
//Check for error / IF any error happens then frame will load with content
try {
if(Ext.getDom('hiddenframe-frame').contentDocument.body.innerHTML.length>0){
Ext.util.Cookies.set('fileDownload', null, new Date("January 1, 1970"),application.contextPath+'/');
Ext.util.Cookies.clear('fileDownload',application.contextPath+'/');
failureCallback();
//Cleanup
Ext.getDom('hiddenframe-frame').contentDocument.body.innerHTML = "";
return;
}
}
catch (e) {
console.log(e);
}
console.log('polling..');
// If we are here, it is not loaded. Set things up so we check the status again in 100 milliseconds
window.setTimeout('FileDownload.isFinished('+successCallback+','+failureCallback+')', 100);
};
Usage :
FileDownload.downloadFile({
url : url,
params : params,
success : function(){
//Success call back here
},
failure : function(){
//Failure callbak here
}
});
In the http response you need to add a cookie nammed fileDownload = true
I just had to ad to the success function of the ajax request:
window.open('urltothefile.ext')