I'm trying to update an icon with axios and put method on a laravel/vue app.
I'm always getting the error : icon must be an image.
I've correctly inserted my headers : content-type": "multipart/form-data" in the config variable.
async updateSolution({
commit
}, payload) {
const id = payload.id;
const config = payload.config;
const solution = payload.data;
try {
console.log(solution.get('icon'));
const res = await this.$axios.$put(`/api/solutions/${id}`, {
config,
name: solution.get('name'),
description: solution.get('description'),
icon: solution.get('icon'),
});
commit('UPDATE_SOLUTION', res);
} catch (error) {}
},
If I do a console.log(solution.get('icon') here is the output :
File {name: 'img.png', lastModified: 1660039998282, lastModifiedDate: Tue Aug 09 2022 12:13:18 GMT+0200 (Central European Summer Time), webkitRelativePath: '', size: 9026, …}
lastModified: 1660039998282
lastModifiedDate: Tue Aug 09 2022 12:13:18 GMT+0200 (Central European Summer Time) {}
name: "img.png"
size: 9026
type: "image/png"
webkitRelativePath: ""
[[Prototype]]: File
So it understand well that there is a image file in actions.js vuex file.
Why does it tell me that this is not an image ?
I heard about the workaround with _method parameter, so I've first tried adding the method in formData object :
async editSolution() {
const result = await this.$refs.observer.validate();
this.message = null;
this.errors = [];
let formData = new FormData();
const id = this.id;
const config = {
headers: {
"content-type": "multipart/form-data",
},
};
formData.append("name", this.solutionName);
formData.append("description", this.solutionDesc);
formData.append("icon", this.solutionIcon);
formData.append("_method", "PUT");
this.$emit("edit-data", id, formData, config);
},
Here the output is :
The POST method is not supported for this route.
So the parameter is not recognized apparently.
I also tried to add the parameter in the actions.js vuex file directly.
const res = await this.$axios.$post(`/api/solutions/${id}`, {
_method: 'PUT',
config,
name: solution.get('name'),
description: solution.get('description'),
icon: solution.get('icon'),
})
It gives me the same error than using this.$axios.$put() call :
icon must be an image.
Thanks for your help,
Related
I am attempting to set up Plaid in my app, and am following the Quickstart guide for Node.js and Express. When I call the client.linkTokenCreate function I am getting a status 400 Bad Request response. I believe my code exactly matches the quickstart, and I am using sandbox mode, so I am unsure where I am going wrong.
const { Configuration, PlaidApi, PlaidEnvironments, Products, CountryCode } = require("plaid");
const configuration = new Configuration({
basePath: PlaidEnvironments[process.env.PLAID_ENV],
baseOptions: {
headers: {
"PLAID-CLIENT-ID": process.env.PLAID_CLIENT_ID,
"PLAID-SECRET": process.env.PLAID_SECRET,
},
},
});
console.log(configuration)
const client = new PlaidApi(configuration);
router.post("/create_link_token", async (req, res) => {
// Get the client_user_id by searching for the current user
// const user = await User.find(...);
// const clientUserId = user.id;
const request = {
user: {
// This should correspond to a unique id for the current user.
client_user_id: "test123",
},
client_name: "Name Of App",
products: [Products.Auth],
language: "en",
webhook: 'https://app.com',
country_codes: [CountryCode.Us],
};
try {
console.log("request",process.env.PLAID_CLIENT_ID,process.env.PLAID_SECRET)
const createTokenResponse = await client.linkTokenCreate(request);
console.log("createTokenResponse", createTokenResponse);
res.status(200).json(createTokenResponse);
} catch (error) {
console.log("error", error.message)
res.send(error.message)
}
});
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);
});
});
In my Lambda function, I want to conditionally put items into my DynamoDB only if the value DOESN'T EXIST already. I saw multiple different sources where they use this ConditionExpression and i cant figure out whats wrong with that.
body = await dynamo.put({
TableName: 'polit-stream',
Item: {
urlPath: data.urlPath,
},
ConditionExpression: "attribute_not_exists(urlPath)"
}).promise();
The put will always be successful, even if my secondary index value (urlPath) already exists.
Full Code:
const AWS = require('aws-sdk');
const crypto = require("crypto");
const dynamo = new AWS.DynamoDB.DocumentClient();
/**
* Demonstrates a simple HTTP endpoint using API Gateway. You have full
* access to the request and response payload, including headers and
* status code.
*
* To scan a DynamoDB table, make a GET request with the TableName as a
* query string parameter. To put, update, or delete an item, make a POST,
* PUT, or DELETE request respectively, passing in the payload to the
* DynamoDB API as a JSON body.
*/
exports.handler = async(event, context) => {
let body;
let statusCode = '200';
const headers = {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '* '
}
const data = JSON.parse(event.body);
const generateUUID = () => crypto.randomBytes(16).toString("hex");
try {
switch (event.httpMethod) {
case 'DELETE':
body = await dynamo.delete(JSON.parse(event.body)).promise();
break;
case 'GET':
body = await dynamo.scan({
TableName: 'db',
IndexName: 'urlPath',
FilterExpression: "urlPath = :urlPath",
ExpressionAttributeValues: {
":urlPath": event.queryStringParameters.urlPath
}
},
function(data) {
}).promise();
break;
case 'POST':
body = await dynamo.put({
TableName: 'db',
Item: {
id: generateUUID(),
name: data.name,
date: data.date,
place: data.place,
goals: data.goals,
type: data.type,
org: data.org,
email: data.email,
urlPath: data.urlPath,
createdAt: new Date().toISOString()
},
ConditionExpression: "attribute_not_exists(urlPath)"
}).promise();
break;
case 'PUT':
body = await dynamo.update(JSON.parse(event.body)).promise();
break;
default:
throw new Error(`Unsupported method "${event.httpMethod}"`);
}
}
catch (err) {
statusCode = '400';
body = err.message;
}
finally {
body = JSON.stringify(body);
}
return {
statusCode,
body,
headers,
};
};
Your error is that you misunderstood what ConditionExpression can do. Your full PutItem code is:
body = await dynamo.put({
TableName: 'db',
Item: {
id: generateUUID(),
name: data.name,
date: data.date,
place: data.place,
goals: data.goals,
type: data.type,
org: data.org,
email: data.email,
urlPath: data.urlPath,
createdAt: new Date().toISOString()
},
ConditionExpression: "attribute_not_exists(urlPath)"
}
What did you expect ConditionExpression: "attribute_not_exists(urlPath)" to do?
Apparently you thought that it will check whether any item exists with this value of urlPath. But this is not, unfortunately, what this expression does. What it does is to look at one specific item - the item with the same key (I don't know what is your key, id?) and check whether this specific item has a urlPath attribute (with any value).
If urlPath was the item's key, this work like you hoped it would. If the urlPath is unique (which it seems it is, according to what you wanted to do) then it can indeed serve as the item key.
In order to use the ConditionExpression you need to provide name and value for the attributes. Try this:
await dynamo.put({
TableName: 'db',
Item: {
id: generateUUID(),
name: data.name,
date: data.date,
place: data.place,
goals: data.goals,
type: data.type,
org: data.org,
email: data.email,
urlPath: data.urlPath,
createdAt: new Date().toISOString(),
},
ConditionExpression: "attribute_not_exists(#u) or (#u=:urlPath)",
ExpressionAttributeNames: { "#u": "urlPath" },
ExpressionAttributeValues: { ":urlPath": data.urlPath },
});
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.
following is the response info:
"%PDF-1.4\n%����\n2 0 obj\n<>stream\nx��X�s�F\u0010�\u0019����$\u0010JaF\u000f\t\t�*:Iw�:�h������-ڀg/}]�yk��Z\u0002��0Vڈ��&��\n��ɐֳ�L\u0012?�4\u000bi���\u001b�D\u0017\tPقYl���\u0019p\u0010:\-g���Oǜ�F�\u0019�L�&�_c6�'\u0016��cv���fhm�ҏ?;�ǴK�U��d\u0007�!����qG{,k�M��\u001e۬�)-�E�GU¢\u0019�\u0003(�����q2R�\u001c%K�vC���[�;�j\u0004�E�PO�hH��dk\u0011\fN����騈���\u000fs=8���9\u001fY�\u00185t\u001d��A0Sa��!\u000e��i\u000f�(1R�q����>�\u0017�i��\u0017<�$��\u0015�;�|/^�;���v̺H\u0019�1�\t�#��m�?�\u00137q�\u0004�\\u0010ְ'M鴨\u000b���0�9B1�ێ���=�K,Z\"'���\u0019���3��W\u0010q\u0000A�D��� �Hh���\u0017�c�k��̉�i�W\u000b�Mph�P�#��0W:ʥ\u0003�*ӕ�9���\u0015OG��\u000e�$A)>�\u0018H*�R�1 7��~ch\u001a�CUfQ�j�9��+��K��Џ�\u001a{�G��)\f�D\u0012\f���(C\u0005��?ݗ��m�������c��0Ϩ�v#*#Hp�\u0019�Y�!��7�-�\u001b�a�w�3��&�T0q=�K�-ؚ�\u0018\u000e�)���]N�P\u0019ZB.�$w\u0015�\u0006n�&6|
Hey yes there is but it takes a little custom work!
Here is how you can do it to work with scaphold.io but you could extend this to your own implementation as well!
Basically what is happening is you attach the file at the root level of a multipart/form-data request and then from the input in your GraphQL variables you point to the key of the file in the request. Here is some code to show how you can retrofit and ApolloClient instance with a file-ready network interface that you can then feed into Angular2Apollo.
import { createNetworkInterface } from 'apollo-client';
// Create a file-ready ApolloClient instance.
export function makeClientApolloFileHandler() {
const graphqlUrl = `https://scaphold.io/graphql/my-app`;
const networkInterface = createNetworkInterface(graphqlUrl);
networkInterface.query = (request) => {
const formData = new FormData();
// Parse out the file and append at root level of form data.
const varDefs = request.query.definitions[0].variableDefinitions;
let vars = [];
if (varDefs && varDefs.length) {
vars = varDefs.map(def => def.variable.name.value);
}
const activeVars = vars.map(v => request.variables[v]);
const fname = find(activeVars, 'blobFieldName');
if (fname) {
const blobFieldName = fname.blobFieldName;
formData.append(blobFieldName, request.variables[blobFieldName]);
}
formData.append('query', printGraphQL(request.query));
formData.append('variables', JSON.stringify(request.variables || {}));
formData.append('operationName', JSON.stringify(request.operationName || ''));
const headers = { Accept: '*/*' };
if (localStorage.getItem('scaphold_user_token')) {
headers.Authorization = `Bearer ${localStorage.getItem('scaphold_user_token')}`;
}
return fetch(graphqlUrl, {
headers,
body: formData,
method: 'POST',
}).then(result => result.json());
};
const clientFileGraphql = new ApolloClient({
networkInterface,
initialState: {},
});
return clientFileGraphql;
}
After this function does its work on the request you might have FormData that looks like this (if it were encoded in JSON):
{
"query": "mutation CreateFile($input:CreateFileInput) { createFile(input: $input) { ... }",
"variables": {
"input": {
"blobFieldName": "myFile",
"name": "MyFileName!"
}
},
// Note how the blobFieldName points to this key
"myFile": <Buffer of file data in multipart/form-data>
}
The server would then need to understand how to interpret this in order to look for the file in the payload and associate it with the correct object etc.
Hope this helps!