FineUploader 5.14.0 - setParams not working with large files - fine-uploader

I've had the following code working for quite a while now (over a year) but a user has tried to upload a 14MB file and the extra data I post along with the upload seems to not get posted anymore.
In Chrome dev tools I look at the header of the (single) XHR and I see the data in the "Form data" section but nothing get's to the server which I don't understand.
Files that are a few MB or smaller work without issue. I've not found a magic MB limit yet.
The extra data is in the onUpload call back. board_hash is in the head of page.
var fu_instance = new qq.FineUploader(
{
element: $uploader[0],
template: 'agenda_file_template',
debug: true,
request: {
endpoint: '/m/upload',
forceMultipart: false,
customHeaders: {
Accept: 'application/json'
}
},
autoUpload: false,
messages:
{
noFilesError: "There is no files to upload. Select or drag and drop some files to upload.",
},
failedUploadTextDisplay:
{
mode: 'custom',
responseProperty: 'error'
},
callbacks:
{
onSubmit: function(id, filename)
{
// File added to upload
$uploader.addClass('hide-drop-msg');
$btn_submit_upload.html('Upload').show();
unsaved = true;
},
onUpload: function(id, name)
{
fu_instance.setParams({'board_hash': board_hash, 'parent': $parent.val()});
},
onCancel: function(id, name)
{
// Actually onBeforeCancel
if ($uploader.find('ul.qq-upload-list li').length == 1)
{
// There is currently 1 & it's about to be axed
$uploader.removeClass('hide-drop-msg');
$btn_reset_uploads.hide();
$btn_submit_upload.html('Upload').show();
unsaved = false;
}
},
onError: function(id, name, reason, resp)
{
// Specific file error
if (resp.hasOwnProperty('auth_expired'))
{
window.location.href = auth_url;
}
},
onComplete: function(id, name, resp)
{
if (resp.success)
{
var $parent_el = $('#'+$parent.val());
$parent_el.find('.files').append(resp.html);
$parent_el.find('.no-agenda-files').hide();
}
},
onAllComplete: function(succeeded, failed)
{
// Every file is done
$btn_submit_upload.hide();
$btn_reset_uploads.show();
unsaved = false;
}
}
});
My understanding is that chunking is off by default. Have I configured this wrong or am I in the wrong call back?

Related

How to work with pdf files on back4app parse server

i have been exploring back4app parse server. i am tiered of finding documentation for pdf files. I am trying to generate some pdf files on back4app parse server from its cloud function.i do not see any documentation for it. will some one guide me to find it and little enlightment will be highly appreciated.
edit:
pdf creator library out there ask for output path but in back4app we don't have early access to path. we create new file passing it data and then save it to object. how do we achieve the order.
I some how managed get it done, thank you #Davi macedo. but there is some problem, i created pdf locally(root) cloud code,deleting it each time is envitable . this could be problem for more requests.
can someone improve little bit. would be great.
Here is my code.
I have used pdf-creator-node for creating pdf.
var pdf = require("pdf-creator-node");
var fs = require("fs")
var path = require('path')
const pdf2base64 = require('pdf-to-base64');
Parse.Cloud.define("pdf", async (req) => {
//creating pdf
// var html = fs.readFileSync("template.html", "utf8");
var html = fs.readFileSync(path.resolve(__dirname, 'template.html'), {
encoding: 'utf-8' });
var options = {
format: "A3",
orientation: "portrait",
border: "10mm",
header: {
height: "45mm",
contents: '<div style="text-align: center;">Author: Shyam Hajare</div>'
},
footer: {
height: "28mm",
contents: {
first: 'Cover page',
2: 'Second page', // Any page number is working. 1-based index
default: '<span style="color: #444;">{{page}}</span>/<span>{{pages}}</span>', // fallback value
last: 'Last Page'
}
}
};
var users = [
{
name: "Shyam",
age: "26",
},
{
name: "Navjot",
age: "26",
},
{
name: "Vitthal",
age: "26",
},
];
var document = {
html: html,
data: {
users: users,
},
path: path.resolve(__dirname, './pdfs', 'my_file.pdf'),//using path is necessary
type: "",
};
return pdf
.create(document, options)
.then((res) => {
return pdf2base64(path.resolve(__dirname, "/usr/src/app/data/cloud /pdfs/my_file.pdf")) //this path /usr/src/app/data/cloud/pdfs still mystery to me.
.then(
(response) => {
// console.log(response); //cGF0aC90by9maWxlLmpwZw==
const saveFiles = async () => {
//creating file
const parseFile = new Parse.File('pdfFile.pdf',{base64:response});
// console.log(parseFile)
//saving file
const responseFile = await parseFile.save();
const Document = Parse.Object.extend('Document');
const document = new Document();
//saving it to object.
document.set('document', responseFile);
await document.save();
}
saveFiles();
}
)
.catch(
(error) => {
console.log(error); //Exepection error....
}
)
console.log(res);
})
.catch((error) => {
console.error(error);
});
});

Make an ajax call inside of a .map()

I am upgrading jquery and saw that the "async: false" option has been deprecated. This makes sense and in 99.9% of cases I agree with the rationale, but I have a case where I think I really need it and I cannot for the life of me figure out how to make this work with a purely async ajax call no matter how I use promises or async/await.
My use case is in a Vue component and I have an array of contacts. What I need to do is map over the contacts and validate them. One such validation requires a quick check of email validity via a "check_email" ajax endpoint.
Once I validate (or not) the list, I then submit the list (if valid) or show error messages (if invalid).
My code is something like this
sendContacts: function() {
valid = this.validateContacts()
if (valid) {
// send the contacts
} else {
return // will display error messages on contacts objects
}
},
validateContacts: function() {
this.contacts = this.contacts.map((contact) => {
if (!contact.name) {
contact.validDetails.name = false
contact.valid = false
return contact
}
if (!contact.email) {
contact.validDetails.emailExists = false
contact.valid = false
return contact
}
if (!check_email(email)) { // THIS IS ASYNC NOW WHAT DO I DO
contact.valid = false
contact.validDetails.emailFormat = false
}
return contact
}
var validData = this.contacts.map(c => {
return c.valid
})
return !validData.includes(false)
}
function check_email(email) {
const url = `/api/v1/users/check-email?email=${email}`
let valid = false
$.ajax({
url: url,
type: 'POST',
async: false, // I can't do this anymore
headers: {
'X-CSRFToken': csrfToken
},
success: resp => {
valid = true
},
error: err => {
}
})
return valid
}
my data function:
data: function() {
return {
contacts: [this.initContact()],
showThanks: false,
emailError: false,
blankEmail: false,
blankName: false
}
},
methods: {
initContact: function() {
return {
name: null,
email: null,
title: null,
validDetails: this.initValidDetails(),
valid: true,
}
},
initValidDetails: function() {
return {
emailDomain: true,
emailExists: true,
emailFormat: true,
name: true
}
}
}
Again, I have tried async/await in every place I could think of and I cannot get this to validate properly and then perform correct logic regarding whether the send contacts function part of the function should fire. Please help!
Once any part of your validation is asynchronous, you must treat the entire thing as asynchronous. This includes when calling validateContacts in sendContacts.
First, you should change check_email to return Promise<bool>. It's usually a bad idea to include jQuery in a Vue project so let's use fetch instead (Axios being another popular alternative).
async function check_email(email) {
const params = new URLSearchParams({ email })
const res = await fetch(`/api/v1/users/check-email?${params}`, {
method: 'POST',
headers: {
'X-CSRFToken': csrfToken
}
})
return res.ok
}
As for your async validation logic, it's best to map your contacts to an array of promises and wait for them all with Promise.all.
async validateContacts () {
const validationPromises = this.contacts.map(async contact => {
if (!contact.name) {
return {
...contact,
valid: false,
validDetails: {
...contact.validDetails,
name: false
}
}
}
if (!contact.email) {
return {
...contact,
valid: false,
validDetails: {
...contact.validDetails,
emailExists: false
}
}
}
if (await check_email(contact.email)) { // await here
return {
...contact,
valid: false,
validDetails: {
...contact.validDetails,
emailFormat: false
}
}
}
return { ...contact, valid: true }
})
// now wait for all promises to resolve and check for any "false" values
this.contacts = await Promise.all(validationPromises)
return this.contacts.every(({ valid }) => valid)
}
As mentioned, now you need to treat this asynchronously in sendContacts
async sendContacts () {
if (await this.validateContacts()) {
// send the contacts
}
}

Get the new resource id after an event has been dragged or resized in FullCalendar

I'm using FullCalendar with the Scheduler plugin and I'm trying to get the new resource id for the event that has just been dragged or resized. If I console.log the event argument of eventResize or eventDragStop functions I always get the initial resource id of the event.
Any idea how can I achieve this?
Bellow is the code I have so far:
$('#calendar').fullCalendar({
schedulerLicenseKey: 'CC-Attribution-NonCommercial-NoDerivatives',
locale: 'ro',
header: {
left: '',
center: 'title',
right: ''
},
defaultView: 'agendaDay',
views: {
agenda: {
titleFormat: 'dddd, D MMMM'
}
},
minTime: '07:00:00',
maxTime: '24:00:00',
slotDuration: '00:30:00',
slotLabelFormat: 'HH(:mm)',
allDaySlot: false,
resources: {
url: '/some/endpoint/here',
type: 'POST',
data: {
type: $('#type').val()
}
},
events: '/some/other/endpoint/here',
eventOverlap: false,
eventConstraint: {
start: '07:00',
end: '24:00'
},
dayClick: function(date, jsEvent, view, resourceObj) {
var check = moment(date).format('YYYY-MM-DD');
var today = moment(new Date()).format('YYYY-MM-DD');
if (check >= today) {
// Some logic here
}
},
eventClick: function(calEvent, jsEvent, view) {
var check = moment(calEvent.start).format('YYYY-MM-DD');
var today = moment(new Date()).format('YYYY-MM-DD');
if (check >= today) {
// Some logic here
}
},
eventResize: function(event, delta, revertFunc, jsEvent, ui, view) {
console.log('Resize', event, jsEvent);
},
eventDragStop: function(event, jsEvent, ui, view) {
console.log('Drag', event);
}
});
The documentation for "eventDragStop" (https://fullcalendar.io/docs/eventDragStop) explicitly states
It is triggered before the event’s information has been modified
So that explains why the resource ID has not changed when you log it from there.
The callback you want to be handling instead is "eventDrop" (https://fullcalendar.io/docs/eventDrop), which is triggered when the dragging stops and the event data has been updated to reflect its new location.
For example:
eventDrop: function( event, delta, revertFunc, jsEvent, ui, view ) {
console.log("Resource: " + event.resourceId);
}
should get you the information you want.
Obviously if you only resize an event that cannot change the resource it belongs to, so that situation is not relevant to your issue.

How do I get file names in Fineuploader's onAllComplete event

I'm trying to retrieve the filenames for the successfully uploaded files in the onAllComplete() event. My code below returns "undefined" for the getName() call. I'm not sure if the file name is in fact no longer defined at this point or if I'm attempting to access it incorrectly. Any help will be much appreciated. Thanks!
var uploader = $('#fine-uploader').fineUploader({
...
callbacks: {
onAllComplete: function(succeeded, failed) {
if (failed.length > 0) {
alert("Error: Some files were not uploaded");
} else {
if (succeeded.length > 0 ) {
alert("Success!");
}
this.reset();
}
for (var id in succeeded) {
alert(this.getName(id))
}
},
...
},
...
});
The this.reset() is clearing the file names.

Fine Uploader - This is an unrecoverable error, we must restart the upload entirely on the next retry attempt

Using Fine Uploader 5.0.6 i am trying to send both the original and scaled image onto my s3 bucket. it works until i set a minimum size limit with minSizeLimit in the validation options. When i leave this out or uncomment it it works fine but when it's in i get this output in my console:
POST http://zippi.bucket.artist.s3-eu-west-1.amazonaws.com/ 400 (Bad Request)
[Fine Uploader 5.0.6] This is an unrecoverable error, we must restart the upload entirely on the next retry attempt.
I have retry:EnableAuto:true so this runs through 3 times with the same result until stopping. This only applies to the scaled image, the main image uploads fine without issue
My signature.php page does not include any references to a minimum file size, just maximum in
$expectedMaxSize = 10000000;
In this function below. Could this be causing it?:
function isPolicyValid($policy) {
global $expectedMaxSize, $expectedBucketName;
$conditions = $policy["conditions"];
$bucket = null;
$parsedMaxSize = null;
for ($i = 0; $i < count($conditions); ++$i) {
$condition = $conditions[$i];
if (isset($condition["bucket"])) {
$bucket = $condition["bucket"];
}
else if (isset($condition[0]) && $condition[0] == "content-length-range") {
$parsedMaxSize = $condition[2];
}
}
return $bucket == $expectedBucketName && $parsedMaxSize == (string)$expectedMaxSize;
}
Code on my actual page:
var manualuploader = jQuery("#fine-uploader").fineUploaderS3({
request: {
endpoint: 's3.bucket.files.s3-eu-west-1.amazonaws.com',
accessKey: 'XXXXXXXXXXXX'
},
signature: {
endpoint: 'signature.php'
},
uploadSuccess: {
endpoint: 'success.php'
},
iframeSupport: {
localBlankPagePath: 'success.html'
},
multiple: false,
retry: {
enableAuto: true
},
autoUpload: false,
scaling: {
sizes: [
{name: "web", maxSize: 500}
]
},
validation: {
allowedExtensions: ['jpeg', 'jpg', 'png'],
sizeLimit: 10000000,
minSizeLimit: 400000 // THIS IS THE LINE
},
objectProperties: {
key: function (fileId) {
var filename = jQuery('#fine-uploader').fineUploader('getName', fileId);
var uuid = jQuery('#fine-uploader').fineUploader('getUuid', fileId);
var ext = filename.substr(filename.lastIndexOf('.') + 1);
folder_name = folder_name.replace(/\s/g, '-');
var new_filename;
if (filename.indexOf('(web)') >= 0){
new_filename = '/the_web_version.';
}
else {
new_filename = '/the_original_version.';
}
return artist + '/' + folder_name + new_filename + ext;
}
}
}).on('submitted', function(event, id, name) {
//....
}).on('cancel', function(event, id, name) {
//....
}).on('progress', function(event, id, fileName, loaded, total) {
//....
}).on('complete', function(event, id, name, response) {
if (response.success) {
//...
}
});
jQuery('#triggerUpload').click(function() {
manualuploader.fineUploaderS3('uploadStoredFiles');
});
If you set a minimum file size validation option, Fine Uploader will pass that value on to S3 to ensure it is respected. Most likely, a scaled image is smaller than that minimum size. I suggest simply removing this restriction if you are dealing with dynamically scaled images.

Resources