How to work with pdf files on back4app parse server - parse-platform

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);
});
});

Related

Getting HTTP response code -1 from POST request

I'm trying to upload a file to a server and I keep getting a error response code of -1.
This is for a NativeScript app built with Angular and I'm using the NativeScript HTTP Background plugin.
component.ts
onCreateRecipe() {
console.log(this.imageUris);
const recipeForm = {
name: this.form.get('name').value,
description: this.form.get('description').value,
photo: this.imageUris[0],
ingredients: this.form.get('ingredients').value,
// steps: this.form.get('steps').value,
// tag: 'poultry recipe'
type: this.recipeType
};
console.log(recipeForm);
this.apiService.postRecipe(recipeForm).subscribe(res => console.log(res));
}
service.ts
postRecipe(recipe) {
const session = bghttp.session('image-upload');
const subject = new Subject<any>();
const request = {
url: `${this.apiURL}/recipe/1`,
method: 'POST',
headers: {
"Content-Type": "application/octet-stream"
},
description: 'test'
};
let task: bghttp.Task;
const params = [
{ name: 'name', value: recipe.name },
{ name: 'description', value: recipe.description },
{ name: 'photo', filename: recipe.photo, mimeType: 'image/png' },
{ name: 'ingredients', value: JSON.stringify(recipe.ingredients) }
];
console.log(params);
task = session.multipartUpload(params, request);
task.on('responded', (event: any) => {
if (event.data && event.data.error) {
subject.error(event.data);
} else {
subject.next(event.data);
}
});
// task.on('error', (event) => subject.error(event));
task.on('error', (e) =>console.log("received " + e.responseCode + " code."));
return subject;
}
Note: ingredients is a FormArray that's why I have to use JSON.Stringify to pass it to the plugin. recipe.photo is a file path to the image.
I expect all the data, including the image file, to be uploaded to the server but right now only the image is being uploaded.

How use MediaFilePicker and PhotoEditor plugins in Nativescript

I am trying to use MediaFilePicker on nativescript and at the same time use the PhotoEditor plugin to crop/edit the photo taken from the camera but I don't make it work... here is part of my code:
let options: ImagePickerOptions = {
android: {
isCaptureMood: true, // if true then camera will open directly.
isNeedCamera: true,
maxNumberFiles: 1,
isNeedFolderList: true
}, ios: {
isCaptureMood: true, // if true then camera will open directly.
maxNumberFiles: 1
}
};
let mediafilepicker = new Mediafilepicker();
mediafilepicker.openImagePicker(options);
mediafilepicker.on("getFiles", function (res) {
let results = res.object.get('results');
let result = results[0];
let source = new imageSourceModule.ImageSource();
source.fromAsset(result.rawData).then((source) => {
const photoEditor = new PhotoEditor();
photoEditor.editPhoto({
imageSource: source,
hiddenControls: [],
}).then((newImage) => {
}).catch((e) => {
reject();
});
});
});
The result object of the FilePicker comes like:
{
"type": "capturedImage",
"file": {},
"rawData": "[Circular]"
}
I believe if the picture was taken from the camera, then use the rawData field, but I dont know which format is coming and how to give it to PhotoEditor pluging to play with it.
Any suggestions?
Thanks!
The issue was at this line source.fromAsset(result.rawData) here, result.rawData is not an ImageAsset but it's PHAsset. You will have to create an ImageAsset from PHAsset and pass it on to fromAsset. So it would look like,
import { ImageAsset } from "tns-core-modules/image-asset";
....
....
imgSource.fromAsset(new ImageAsset(img)).then((source) => {
const photoEditor = new PhotoEditor();
console.log(source === imgSource);
photoEditor.editPhoto({
imageSource: source,
hiddenControls: [],
}).then((newImage: ImageSource) => {
console.log('Get files...');
// Here you can save newImage, send it to your backend or simply display it in your app
}).catch((e) => {
//reject();
});
});

Gatsby - fetching remote images with createRemoteFileNode

I've been trying to fetch images from remote URL to Gatsby Source File system, to take advantage of lazy loading with gatsby-image plugin. I have a restful API which returns json with a string containing the image url. I followed this guide as I'm quite new to Gatsby Node Api and wasn't sure how to tackle this. Everything worked well until the point with adding additional properties to image with createNodeField. The properties seem to be added (I can see the object with fields property when I log the fileNode to the console. However, when trying to query the images, I get an error:
I'm wondering if there's something wrong in my code or is it due to the changes in gatsby? I'm using gatsby version 2.0.2. Is there a better option to somehow add additional properties to the image in order to be able to query just the needed ones?
Here's how my gatsby.node.js looks like:
const axios = require('axios');
const { createRemoteFileNode } = require(`gatsby-source-filesystem`);
exports.sourceNodes = ({ actions, createNodeId, node, store, cache } => {
const { createNode, createNodeField } = actions;
const processProject = project => {
project.photos.forEach(async photo => {
let fileNode;
try {
fileNode = await createRemoteFileNode({
url: photo.photo.url,
store,
cache,
createNode,
createNodeId: id => `projectPhoto-${photo.id}`,
});
await createNodeField({
node: fileNode,
name: 'ProjectPhoto',
value: 'true',
});
await createNodeField({
node: fileNode,
name: 'created_at',
value: photo.created_at,
});
} catch (error) {
console.warn('error creating node', error);
}
});
}
return axios.get(baseApiUrl).then(res => {
res.data.forEach(project => {
const nodeData = processProject(project);
createNode(nodeData);
});
});
}
In the end it seems that using .forEach with async/await was messing stuff up for some reason. Doing everything in for of loop, fixed the problem, although eslint was complaining about that a lot. Here's the code:
const axios = require('axios');
const { createRemoteFileNode } = require(`gatsby-source-filesystem`);
exports.sourceNodes = ({ actions, createNodeId, node, store, cache } => {
const { createNode, createNodeField } = actions;
const processProject = project => {
for (const photo of project.photos) {
let fileNode;
try {
fileNode = await createRemoteFileNode({
url: photo.photo.url,
store,
cache,
createNode,
createNodeId: id => `projectPhoto-${photo.id}`,
});
await createNodeField({
node: fileNode,
name: 'ProjectPhoto',
value: 'true',
});
await createNodeField({
node: fileNode,
name: 'created_at',
value: photo.created_at,
});
} catch (error) {
console.warn('error creating node', error);
}
}
}
return axios.get(baseApiUrl).then(res => {
res.data.forEach(project => {
const nodeData = processProject(project);
createNode(nodeData);
});
});
}

Vuejs function with multiple data

I have two data table in vue app.
Cash [code, description,cash]
Upload [bank, id]
For my update function, i need to take [bank, id] from upload and [cash] from cash. i don't know how, can someone help please ? Thank you. This is my code
This is my vuejs
var app = new Vue({
el: '#app',
data: {
cash: {
codeentry: '',
description: '',
cash: '',
},
upload: {
bank: '',
id: '',
},
},
methods: {
updateBank: function () {
axios.put('/updatebank', this.upload, this.cash)
.then(response => {
if (response.data.etat) {
this.upload.id = response.data.etat.id
this.upload.bank = response.data.etat.bank
this.cash.cash = response.data.etat.cash
}
})
.catch(error => {
console.log('errors: ', error)
})
},
}
});
My route :
Route::put('/updatebank', 'CoinController#updateBank');
Controller :
public function updateBank(Request $request)
{
$coin = Coin::findOrFail($request->id);
$coin->bank = ($request->bank - $request->cash);
$coin->save();
}
When i execute my function and see the report. Only this.upload is token in consideration.
If you mean to have the two data in one object, you can make a new object from the two objects
Es6 Example:
const {bank,id} = this.upload;
const {cash} = this.cash;
const my_data = {
bank, id, cash
}
Older Js example
var my_data = {
cash: this.cash.cash,
bank: this.upload.bank,
id: this.upload.id,
}
Otherwise, if you want to have both in the request as separate objects then wrap around them {}
var my_data = {
upload: this.upload,
cash: this.cash
}
Finally:
axios.put('/updatebank', my_data)
...
Update: It appears you don't want to merge those objects as different sub-object so your updateBank method would be like so:
updateBank: function () {
const my_data = {
cash: this.cash.cash,
bank: this.upload.bank,
id: this.upload.id,
};
axios.put('/updatebank', my_data)
.then(response => {
if (response.data.etat) {
this.upload.id = response.data.etat.id
this.upload.bank = response.data.etat.bank
this.cash.cash = response.data.etat.cash
}
})
.catch(error => {
console.log('errors: ', error)
});
}
Just a side observation, are you sure the this in the response references your Vue object?

Avoid adding reactive properties to a Vue instance or its root $data at runtime - declare it upfront in the data option.

I am a bit confused using VueJS2. I added a few variables to the data container for sending it to my API. That works fine but Vue is throwing me a warning/error message which I don't know how to solve:
Avoid adding reactive properties to a Vue instance or its root $data
at runtime - declare it upfront in the data option.
var app = new Vue({
el: '#app',
data: {
incidentReference: '',
streetName: '',
latitude: '',
longitude: '',
featureTypeId: 1,
archived: 0
},
computed: {
href() {
return '#' + this.name.toLowerCase().replace(/ /g, '-');
}
},
mounted: function () {
this.getIncidents();
},
methods: {
onSubmit() {
axios.post('/api/v1/incidents', this.$data)
.then(response => alert('Success'))
.catch(error => {
console.log(error.response);
})
},
getIncidents: function() {
console.log('getIncidents');
var self = this;
axios.get('/api/v1/incidents').then(function(response) {
// set data on vm
console.log(response.data);
var incidentsReceived = response.data.data.map(function (incident) {
return incident;
});
Vue.set(self, 'incidents', incidentsReceived);
});
}
}
});
You're creating a new reactive property on the response of your API
Vue.set(self, 'incidents', incidentsReceived);
Not sure if you misspelled property's name or forget to create that property. Just use an existing property on you data section
Vue.set(self, 'incidentReference', incidentsReceived); //change property name
or
data: {
incidents: null, //or create this property
},
In my case during unit testing using Jest, I was setting selected but didn't have on component so got this error.
wrapper.setData({
selected: recipients,
});
So created the property on component and then it's working fine.
In the context of Jest & Vue Test Utils consider declaring data in component:
const Component = {
// ..
data() { return { abc: 'abc'; } }
};
const wrapper = mount(Component, { /*..*/ });
instead of
const Component = { /*..*/ };
const wrapper = mount(Component, { /*..*/ });
wrapper.setData({ abc: 'abc' });
await wrapper.vm.$nextTick();

Resources