My Flask project with Dropzone implementation dont show the file upload progress bar but rather both the 'V' and 'X' icons for each file, like this (the 'v' and 'x' icons are bearly visible below the file name):
, and they appear below the drop box, together with the file name and size, instead of inside the drop box. The files gets uploaded though, but the behaviour is undesired. Has anybody encountered the same problem?
HTML part:
<form id="myProjFileUploadForm" method="post" enctype="multipart/form-data" action="{{ url_for('projects.projects_file_upload') }}">
...
<div id="myFileDropContainer" class="dropzone dz-clickable" style="visibility: hidden">
<div class="dz-default dz-message">
<button class="dz-button" type="button">
Drop files here to upload.
</button>
</div>
</div>
...
</form>
script part:
Dropzone.autoDiscover = true;
myDropzone = new Dropzone("#myProjFileUploadForm", {
autoQueue: true,
clickable: ".dropzone",
paramName: 'file',
url: '/upload',
myFileDropContainer: "#myFileDropContainer",
chunking: true,
forceChunking: true,
retryChunks: true,
retryChunksLimit: 10,
maxFilesize: 2025, // The max file size in Mbytes that is allowed to be uploaded
chunkSize: 10000000, // The chunk size in bytes
autoProcessQueue: true,
timeout: 180000000,
maxFiles: 500000
});
// The function that is invoced when files are dropped in
myDropzone.on("complete", function (file) {
let sStatus = new String(file.status);
let objThisFile = file
sStatus = sStatus.trim();
let sFileName = new String(file.name);
let sLastModifiedDate = new String(file.lastModifiedDate);
let sSize = new String(file.size);
const myObjFile = {
FileName: sFileName, LastModDate: sLastModifiedDate, Size: sSize
}
if (sStatus == 'success') {
$.ajax({
"url": "{{ url_for('projects.save_file_info_to_database') }}",
"type": 'POST',
"data": JSON.stringify(myObjFile),
"contentType": "application/json",
"dataType": 'json',
success: function (response) {
bErr = response.result;
if (bErr) {
objThisFile.status = 'error'
let sErr = response.msg.toString().trim();
if (sErr.length > 0) {
//alert(sErr);
}
}
else {
myDrawFileTable();
}
}
})
}
else {
let sErr = "The following file failed to upload: " + sFileName;
//alert(sErr);
}
});
Related
I have a lot of problem to upload multiple images using AJAX. I write this code:
HTML
<form id="upload" method="post" enctype="multipart/form-data">
<div id="drop" class="drop-area">
<div class="drop-area-label">
Drop image here
</div>
<input type="file" name="file" id="file" multiple/>
</div>
<ul class="gallery-image-list" id="uploads">
<!-- The file uploads will be shown here -->
</ul>
</form>
<div id="listTable"></div>
jQuery/AJAX
$(document).on("change", "input[name^='file']", function(e){
e.preventDefault();
var This = this,
display = $("#uploads");
// list all file data
$.each(This.files, function(i, obj){
// for each image run script asynchronous
(function(i) {
// get data from input file
var file = This.files[i],
name = file.name,
size = file.size,
type = file.type,
lastModified = file.lastModified,
lastModifiedDate = file.lastModifiedDate,
webkitRelativePath = file.webkitRelativePath,
slice = file.slice,
i = i;
// DEBUG
/*
var acc = []
$.each(file, function(index, value) {
acc.push(index + ": " + value);
});
alert(JSON.stringify(acc));
*/
$.ajax({
url:'/ajax/upload.php',
contentType: "multipart/form-data",
data:{
"image":
{
"name":name,
"size":size,
"type":type,
"lastModified":lastModified,
"lastModifiedDate":lastModifiedDate,
"webkitRelativePath":webkitRelativePath,
//"slice":slice,
}
},
type: "POST",
// Custom XMLHttpRequest
xhr: function() {
var myXhr = $.ajaxSettings.xhr();
// Check if upload property exists
if(myXhr.upload)
{
// For handling the progress of the upload
myXhr.upload.addEventListener("progress",progressHandlingFunction, false);
}
return myXhr;
},
cache: false,
success : function(data){
// load ajax data
$("#listTable").append(data);
}
});
// display progress
function progressHandlingFunction(e){
if(e.lengthComputable){
var perc = Math.round((e.loaded / e.total)*100);
perc = ( (perc >= 100) ? 100 : ( (perc <= 0) ? 0 : 0 ) );
$("#progress"+i+" > div")
.attr({"aria-valuenow":perc})
.css("width", perc+"%");
}
}
// display list of files
display.append('<li>'+name+'</li><div class="progress" id="progress'+i+'">'
+'<div class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%;">'
+'</div></div>');
})(i);
});
});
I've tried a various versions and I never succeed to send multiple data through ajax. I have tried in this way what you see above, and now I get only POST informations. I understand why i get POST but I need to send FILES information and I do not know where I'm wrong.
I not work the first time with ajax and often use it for most projects but I have never used to send multiple files and that bothering me now.
Thanks!
Try utilizing json to upload , process file object
html
<div id="drop" class="drop-area ui-widget-header">
<div class="drop-area-label">Drop image here</div>
</div>
<br />
<form id="upload">
<input type="file" name="file" id="file" multiple="true" accepts="image/*" />
<ul class="gallery-image-list" id="uploads">
<!-- The file uploads will be shown here -->
</ul>
</form>
<div id="listTable"></div>
css
#uploads {
display:block;
position:relative;
}
#uploads li {
list-style:none;
}
#drop {
width: 90%;
height: 100px;
padding: 0.5em;
float: left;
margin: 10px;
border: 8px dotted grey;
}
#drop.hover {
border: 8px dotted green;
}
#drop.err {
border: 8px dotted orangered;
}
js
var display = $("#uploads"); // cache `#uploads`, `this` at `$.ajax()`
var droppable = $("#drop")[0]; // cache `#drop` selector
$.ajaxSetup({
context: display,
contentType: "application/json",
dataType: "json",
beforeSend: function (jqxhr, settings) {
// pre-process `file`
var file = JSON.parse(
decodeURIComponent(settings.data.split(/=/)[1])
);
// add `progress` element for each `file`
var progress = $("<progress />", {
"class": "file-" + (!!$("progress").length
? $("progress").length
: "0"),
"min": 0,
"max": 0,
"value": 0,
"data-name": file.name
});
this.append(progress, file.name + "<br />");
jqxhr.name = progress.attr("class");
}
});
var processFiles = function processFiles(event) {
event.preventDefault();
// process `input[type=file]`, `droppable` `file`
var files = event.target.files || event.dataTransfer.files;
var images = $.map(files, function (file, i) {
var reader = new FileReader();
var dfd = new $.Deferred();
reader.onload = function (e) {
dfd.resolveWith(file, [e.target.result])
};
reader.readAsDataURL(new Blob([file], {
"type": file.type
}));
return dfd.then(function (data) {
return $.ajax({
type: "POST",
url: "/echo/json/",
data: {
"file": JSON.stringify({
"file": data,
"name": this.name,
"size": this.size,
"type": this.type
})
},
xhr: function () {
// do `progress` event stuff
var uploads = this.context;
var progress = this.context.find("progress:last");
var xhrUpload = $.ajaxSettings.xhr();
if (xhrUpload.upload) {
xhrUpload.upload.onprogress = function (evt) {
progress.attr({
"max": evt.total,
"value": evt.loaded
})
};
xhrUpload.upload.onloadend = function (evt) {
var progressData = progress.eq(-1);
console.log(progressData.data("name")
+ " upload complete...");
var img = new Image;
$(img).addClass(progressData.eq(-1)
.attr("class"));
img.onload = function () {
if (this.complete) {
console.log(
progressData.data("name")
+ " preview loading..."
);
};
};
uploads.append("<br /><li>", img, "</li><br />");
};
}
return xhrUpload;
}
})
.then(function (data, textStatus, jqxhr) {
console.log(data)
this.find("img[class=" + jqxhr.name + "]")
.attr("src", data.file)
.before("<span>" + data.name + "</span><br />");
return data
}, function (jqxhr, textStatus, errorThrown) {
console.log(errorThrown);
return errorThrown
});
})
});
$.when.apply(display, images).then(function () {
var result = $.makeArray(arguments);
console.log(result.length, "uploads complete");
}, function err(jqxhr, textStatus, errorThrown) {
console.log(jqxhr, textStatus, errorThrown)
})
};
$(document)
.on("change", "input[name^=file]", processFiles);
// process `droppable` events
droppable.ondragover = function () {
$(this).addClass("hover");
return false;
};
droppable.ondragend = function () {
$(this).removeClass("hover")
return false;
};
droppable.ondrop = function (e) {
$(this).removeClass("hover");
var image = Array.prototype.slice.call(e.dataTransfer.files)
.every(function (img, i) {
return /^image/.test(img.type)
});
e.preventDefault();
// if `file`, file type `image` , process `file`
if (!!e.dataTransfer.files.length && image) {
$(this).find(".drop-area-label")
.css("color", "blue")
.html(function (i, html) {
$(this).delay(3000, "msg").queue("msg", function () {
$(this).css("color", "initial").html(html)
}).dequeue("msg");
return "File dropped, processing file upload...";
});
processFiles(e);
} else {
// if dropped `file` _not_ `image`
$(this)
.removeClass("hover")
.addClass("err")
.find(".drop-area-label")
.css("color", "darkred")
.html(function (i, html) {
$(this).delay(3000, "msg").queue("msg", function () {
$(this).css("color", "initial").html(html)
.parent("#drop").removeClass("err")
}).dequeue("msg");
return "Please drop image file...";
});
};
};
php
<?php
if (isset($_POST["file"])) {
// do php stuff
// call `json_encode` on `file` object
$file = json_encode($_POST["file"]);
// return `file` as `json` string
echo $file;
};
jsfiddle http://jsfiddle.net/guest271314/0hm09yqo/
I have 2 of the same components in my laravel blade view, but they are conflicting.
What i'm trying to accomplish:
I've made a vue component that uploads a file to firebase and stores it in my database. In my blade view i have 2 places where i want to use this component. I configure the component with props so the component knows where to store the file.
What going wrong:
Every time i try to upload a file with the second component, i fire the function in the first component. How do i fix that the components can't conflict?
My laravel balde view:
component 1
<uploadfile
:key="comp100"
:user_data="{{ Auth::user()->toJson() }}"
store_path="/users/{{ Auth::user()->username }}/settings/email_backgrounds"
:store_route="'settings.project_email'"
:size="1000"
fillmode="cover"
></uploadfile>
component 2
<uploadfile
:key="comp200"
:user_data="{{ Auth::user()->toJson() }}"
store_path="/users/{{ Auth::user()->username }}/settings/email_backgrounds"
:store_route="'settings.project_email'"
:size="1000"
fillmode="cover"
></uploadfile>
The Vue component:
<template>
<div class="vue-wrapper">
<FlashMessage position="right top"></FlashMessage>
<div v-if="loading" class="lds-dual-ring"></div>
<div class="field">
<div class="control">
<label class="button main-button action-button m-t-20" for="uploadFiles"><span style="background-image: url('/images/icons/upload.svg')"></span>Kies bestand</label>
<input type="file" name="uploadFiles" id="uploadFiles" class="dropinput" #change="selectFile">
</div>
</div>
</div>
</template>
<script>
import { fb } from '../../firebase.js';
export default {
data() {
return {
fileObject: {
filePath: null,
url: null,
file: null,
resizedPath: null
},
loading: false
};
},
mounted() {
console.log(this.size)
console.log(this.fillmode)
},
props: [
'user_data',
'store_path',
'store_route',
'size',
'fillmode'
],
methods: {
selectFile(event)
{
var file = event.target.files[0];
this.fileObject.file = file
this.fileObject.filePath = this.store_path + '/' + file.name
this.fileObject.resizedPath = this.store_path + '/resized-' + file.name
if(file.type == 'image/png' || file.type == 'image/jpeg')
{
this.uploadFile(this.fileObject)
} else {
this.flashMessage.success({
title: 'Oeps!',
message: 'De afbeelding moet een png of een jpeg zijn!',
blockClass: 'success-message'
});
}
},
uploadFile(fileObject)
{
var vm = this
console.log(fileObject)
var storageRef = fb.storage().ref(fileObject.filePath)
var uploadTask = storageRef.put(fileObject.file)
this.loading = true
uploadTask.on('state_changed', function(snapshot){
var progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
},function(error) {
}, function() {
var resizeImage = fb.functions().httpsCallable('resizeImage')
resizeImage({filePath: fileObject.filePath, contentType: fileObject.file.type, watermark: false, size: vm.size, fit: vm.fillmode}).then(function(result){
var downloadRef = fb.storage().ref(fileObject.resizedPath);
downloadRef.getDownloadURL().then(function(url){
fileObject.url = url
vm.loading = false
vm.storeImage(fileObject)
}).catch(function(error){
console.log(error)
})
}).catch(function(error){
});
});
},
storeImage(file)
{
axios.post('/api/app/store_file', {
api_token: this.user_data.api_token,
user: this.user_data,
file: file,
storeRoute: this.store_route
}).then((res) => {
location.reload()
}).catch((e) => {
});
}
}
}
</script>
Does someone know how to fix this?
the dropzone not sending filename on controller
<form method="post" action="{{ route('student.profile.update',$student->id) }}" enctype="multipart/form-data" class=dropzone id="dropzone" files = true >
Dropzone.options.dropzone =
{
maxFilesize: 12,
renameFile: function (file) {
var dt = new Date();
var time = dt.getTime();
return time + file.name;
},
acceptedFiles: ".jpeg,.jpg,.png,.gif",
addRemoveLinks: true,
timeout: 5000,
success: function (file, response) {
console.log(response);
},
error: function (file, response) {
return false;
}
}
I am working on dropzone js programmatically. this is My div,
<div class="dropzone" id="my-dropzone">
<div class="dz-message">
<div class="col-xs-8">
<div class="message">
<p>Drop files here or Click to Upload</p>
</div>
</div>
</div>
<div class="fallback">
<input type="file" name="file" multiple>
</div>
</div>
and rpzone class is
// Dropzone class:
var myDropzone = new Dropzone("div#my-dropzone", { url: "/file/post"});
but when I drag and drop images to dropzone box images are preview with cross symbols (not success upload). then how can I fix this problem?
dropzone.confif.js
var total_photos_counter = 0;
Dropzone.options.myDropzone = {
uploadMultiple: true,
parallelUploads: 2,
maxFilesize: 5,
previewTemplate: document.querySelector('#preview').innerHTML,
addRemoveLinks: true,
dictRemoveFile: 'Remove file',
dictFileTooBig: 'Image is larger than 16MB',
timeout: 10000,
init: function () {
this.on("removedfile", function (file) {
$.post({
url: '/images-delete',
data: {id: file.name, _token: $('[name="_token"]').val()},
dataType: 'json',
success: function (data) {
total_photos_counter--;
$("#counter").text("# " + total_photos_counter);
}
});
});
},
success: function (file, done) {
total_photos_counter++;
$("#counter").text("# " + total_photos_counter);
}
};
after long time spending find the solution. problem is {{ csrf_field() }} not configuring in my div tag,
first Add this to your main blade template in the section:
<meta name="csrf-token" content="{{ csrf_token() }}">
and then configure dropzone.config.js file to csrf
Dropzone.options.myDropzone = {
uploadMultiple: true,
parallelUploads: 2,
maxFilesize: 16,
previewTemplate: document.querySelector('#preview').innerHTML,
addRemoveLinks: true,
dictRemoveFile: 'Remove file',
dictFileTooBig: 'Image is larger than 16MB',
timeout: 10000,
init: function () {
this.on("removedfile", function (file) {
$.post({
url: '/images-delete',
data: {id: file.name, _token: $('[name="_token"]').val()},
dataType: 'json',
success: function (data) {
total_photos_counter--;
$("#counter").text("# " + total_photos_counter);
}
});
});
},
success: function (file, done) {
total_photos_counter++;
$("#counter").text("# " + total_photos_counter);
},
sending: function(file, xhr, formData){
formData.append('_token', $('meta[name="csrf-token"]').attr('content'));
}
};
now it is working fine with correct url
I know this question has been posted a few times, and i haven´t done anything else unless searching for an answer to the behavior i´m having on my grid...the problem is, the create method being called multiples times AFTER inserting the first one...so the first inserts well, the second repeats two times and so on:
I have a inline grid with two buttons on my grid, the first one just inserts "normally", the second button calls this(below) in a kendoWindow:
<div id="fileUploadWindow">
<form id="fileUploadForm" enctype="multipart/form-data" action="ficheiro.php" method="post">
<input style="font-family: roboto;" type="file" id="file" name="file">
<p id="fileUploadFormResult" style="font-family:Roboto;font-size:13px;float:left;margin-top: 15px;"></p>
<button style="display: block;margin-left: 230px;margin-top: 10px;border: solid;border-width: 1px;padding-left: 10px;background: transparent;border-color: #FF9300;font-size: 13px;font-family: roboto;padding-right: 10px;" id="idBtnEnviarFicheiro" name="nameBtnEnviarFicheiro" type="submit">Enviar</button>
</form>
</div>
It´s just a simple form with a input type file, and for this to be called, i have this method:
$(".k-grid-popup", ent.element).on("click", function ()
{
$("#fileUploadWindow").kendoWindow({
actions: ["Close"],
draggable: true,
width: "300px",
height: "65px",
modal: true,
resizable: false,
title: "Inserir Ficheiro",
visible: false,
close:function()
{
}
}).data("kendoWindow").center().open();
$('#fileUploadForm').on('submit',(function()
{
var formData = new FormData($(this)[0]);
ficheiroVal = $("#file").val().split('\\').pop();
$.ajax({
url: 'ficheiro.php',
type: "POST",
data: formData,
processData: false,
contentType: false,
success: function(data)
{
if(data === "")
{
$("#fileUploadFormResult").text("Erro!, por favor tente de novo.");
hypeDocument.getElementById("fileUploadForm").reset();
}
else
{
$("#fileUploadFormResult").text("Envio com Sucesso!.");
ficheiroValReal = data;
$('#gridBaseDados').data('kendoGrid').dataSource.add({idPai:'',tipo:ficheiroValReal, nome:ficheiroVal, dataCriacao: ''});
$('#gridBaseDados').data('kendoGrid').dataSource.sync();
}
},
error: function(data)
{
$("#fileUploadFormResult").text("Erro!, por favor tente de novo.");
}
});
return false;
}));
My grid model is this:
batch: true,
serverPaging: true,
serverSorting: true,
pageSize: 8,
schema:
{
data: "data",
model:
{
id: "idDocumento",
fields:
{
idDocumento: { editable: false, nullable: true, type: "number"},
idPai: { validation: { required: false } },
tipo: { validation: { required: false } },
nome: { validation: { required: true } },
dataCriacao: {type:"string",editable: false},
dataModificacao: {type:"string",editable: false},
}
}
}
I don´t know if ist´s relevant or not, but here is my php code:
<?php
if(isset($_POST["nameBtnEnviarFicheiro"]))
{
if( ($_POST["nameBtnEnviarFicheiro"]) && (empty($_POST['file'])))
{
echo "";
}
else
{
$temp = explode(".", $_FILES["file"]["name"]);
$newfilename = round(microtime(true)) . '.' . end($temp);
move_uploaded_file($_FILES["file"]["tmp_name"], "tabeladocumento/" . $newfilename);
echo $newfilename;
}
}
?>
So, the user clicks on the popup button, and a kendowindow appears with a input file, the users chooses a file and the FIRST time, the grid inserts the record corectly(appearing only one time)...then he closes the kendoWindow, and if he wants to insert a new file, it does...but the record appears TWO times...the create method is called two times and also my ficheiro.php is also called two times.
I´ve also used this(below) in multiple places, like in the create method..also after calling the sync() but nothing seems to work. What it could be?!
$('#gridBaseDados').data("kendoGrid").dataSource.read();
When you close you window you must destroy all widgets inside, to avoid duplicated instances.
http://docs.telerik.com/kendo-ui/intro/widget-basics/destroy
Hope this help