Why can't send form-data in postman - json

Trying to send form-data in postman and sequelize return error:
value cannot be null
But when send raw request with json all ok. Trying body-parser and multer, but nothing working
This is my index.ts
import express from "express";
import fileUpload from "express-fileupload"
...
const app = express()
const PORT = process.env.PORT || 5100
app.use(cors())
app.use(express.json())
app.use('/api', router)
app.use(fileUpload({}))
app.use(errorHandler)
const start = async () => {
try {
await sequelize.authenticate()
await sequelize.sync()
console.log(chalk.cyanBright('Successful conection to data base'));
app.listen(PORT, () => { console.log(chalk.cyanBright(`Server has been started on port ${PORT}`)) })
}
catch (e) {
console.log(e);
}
}
start()
And this is my controller
export const DeviceController = {
async create(req: Request, res: Response, next:nextType) {
try {
const { brandId, typeId, name, price } = req.body
const img = req.files
let filename = 'uuid.v4()' + '.jpg'
img?.mv(path.resolve(__dirname, '..', 'static', filename))
const device = await Models.Device.create({ brandId, typeId, name, price, img: filename })
return res.json(device)
} catch (error: any) {
next(ApiError.badRequest(error.message))
console.log(error);
}

app.use(express.json())
You have body parsing middleware for JSON request bodies.
You don't have body parsing middleware for multipart/form-data request bodies. The documentation for body-parser lists a several middlewares you could use.
Trying body-parser
… which says it doesn't support that format
and multart
… that doesn't appear to exist. Do you mean multiparty? Or maybe multer?
We can't tell you what you did wrong without seeing your attempt.
Re edit:
You said:
const img = req.files
img?.mv(path.resolve(__dirname, '..', 'static', filename))
But the documentation says:
console.log(req.files.foo); // the uploaded file object
The files property contains all the files, indexed by the the names given to them in the multipart request.
You're trying to read that collection of files as if it were a single file.

Related

React LocalStorage issue not stored in localstorage

I am using Local Storage for my login page
but my variables not storing in the local storage I don't know why....
I am using the following code on my button click....
But the APi i am using is correct... It works fine
res.data.status gives true or false,Inside Axios .then => If is used for correct username and password and else is used for incorrct user
This is my Code:
async function handleSubmit(e) {
var url = 'http://localhost/project/login.php?name='+name+"&price="+price;
const formData = new FormData();
formData.append('avatar',"hi")
await axios.post(url, formData)
.then(res => {
if(!res.data.status){
localStorage.setItem('username', name);
alert(res.data.message);
}else{
alert(res.data.message);
}
})
}
if your variable is not stored in the localStorage. that's because of the condition you have. also as you're sure that your API is working fine and you can successfully make a request and receive a response. then the issue is with the condition. because from your code. you're making conditions only if the request is not successful. you don't have the condition for success.
async function handleSubmit(e) {
var url = 'http://localhost/project/login.php?name='+name+"&price="+price;
const formData = new FormData();
formData.append('avatar',"hi")
await axios.post(url, formData)
.then(res => {
if(!res.data.status){ <= remove the !
localStorage.setItem('username', name);
alert(res.data.message);
}else{
alert(res.data.message);
}
})
}

How to save rendered html view files from ExpressJS Routes

I've built few pages of a static website using ExpressJS and PUG to get the advantage of the template engine.
But now I need to export all the raw HTML that is being rendered by all ExpressJS Routes.
Is there any package that can help me to do that? Or I've to write custom command and iterate over all the Routes and save the rendered output?
If a custom command is the only way, how do I iterate over all the routes and get the rendered output?
I couldn't find any library or resource to achieve what I wanted. But with some of my dirty code, hacks, and packages I was able to export all the routes.
Note: Instead of writing a node command to export the htmls, I've added a route to trigger the operations here is the code for the route:
app.use('/export_templates', router.get('/', async function (req, res, next) {
const endpoints = listEndpoints(app);
const failedEndpoints = [];
for (const i in endpoints) {
const endpoint = endpoints[i];
if (endpoint.path == '/export_templates') {
continue;
}
try {
const res = await axios.get('http://'+req.headers.host+''+endpoint.path+'?export=true');
}
catch(error) {
failedEndpoints.push(endpoint.path);
}
}
res.json({
"status": "succes",
"message": "Please check templates folder for the latest exported html templates",
"failed": failedEndpoints
})
}));
Basically this route iterates and makes a request to all the available routes with a export=true parameter.
Then inside every route view function a condition checks if the export parameter is available then calls the exportTemplateFile function with the pug template location and new file name as the function parameter.
If the request doesn't contain export parameter the requested route will simply output what template.
An example route:
router.get('/', function(req, res, next) {
if (req.query.export) {
exportTemplateFile('views/index.pug', 'index.html');
}
res.render('index.pug');
});
And here is the code for 2 util function to complete the export process
function createTemplateFile(filename) {
fs.open(filename,'r',function(err, fd){
if (err) {
fs.writeFile(filename, '', function(err) {
if(err) {
console.log(err);
}
});
}
});
}
function exportTemplateFile(templateLocation, templateName) {
const html = pretty(pug.renderFile(templateLocation));
createTemplateFile('templates/'+templateName);
var stream = fs.createWriteStream('templates/'+templateName);
stream.once('open', function (fd) {
stream.write(html);
stream.end();
});
}
The createTemplateFile function simply creates a new file if it doesn't exist.
The exportTemplateFile function saves the HTML in the html variable rendered by pug and prettifies it with the pretty package and then overwrites the new template file.
Note: In my case all the pug templates were static so I didn't have to pass any context to the pug.renderFile function. But if you need any context to be used inside the pug template you can simply pass that with the template location.
Edited version of the same answer.
First of all thank you so much for solving this problem.
I have made some changes to your code as per new errors.
Here is the code with async and await function for ejs users
const express = require('express')
const ejs = require('ejs')
const fs = require('fs')
const app = express()
const port = 3000
//set the templating engine as ejs
app.set('view engine', 'ejs');
function createTemplateFile(filename) {
fs.open(filename,'r',function(err, fd){
if (err) {
fs.writeFile(filename, '', function(err) {
if(err) {
console.log(err);
}
});
}
});
}
async function exportTemplateFile(templateLocation, templateName) {
var html = await ejs.renderFile(templateLocation);
createTemplateFile('templates/'+templateName);
var stream = fs.createWriteStream('templates/'+templateName);
stream.once('open', function (fd) {
stream.write(`${html}`);
stream.end();
});
}
app.get('/', (req, res, next) => {
res.render('./pages/home')
exportTemplateFile('views/pages/home.ejs', 'index.html');
console.log('file rendered and saved successfully')
})
app.listen(port, () => {
console.log(`App is listening on port ${port}`)
})

Why can't I patch, update, or delete an AppPackage that I created?

I am trying to change the required engine version of an AppPackage that I have posted using v2 of the Design Automation API.
I've tried using Postman and the Forge Node Client. I'm using the Forge documentation as a reference.
https://forge.autodesk.com/en/docs/design-automation/v2/reference/http/AppPackages(':id')-PATCH/
My credentials are correct and I have a valid token, but for some reason I keep getting a 404 Not Found status and an error that says "AppPackage with the name MyPlugin doesn't belong to you. You cannot operate on AppPackage you do not own." Also, I get the same message when I try to delete or update the AppPackage.
That's really weird because I definitely own this AppPackage. I uploaded it with these same credentials and I can view it by doing a GET request to view all of my AppPackages. Furthermore, the name of the AppPackage is correct and I specified the right scope (code:all) when I authenticated.
Why does Design Automation think this AppPackage doesn't belong to me and why can't I patch, update, or delete it?
UPDATE 3/28/2019: Setting the resource value still results in the same error
UPDATE 4/2/2019: Getting a fresh upload URL doesn't work either. I get an internal server error saying "Object reference not set to an instance of an object."
const ForgeSDK = require('forge-apis');
const oAuth2TwoLegged = new ForgeSDK.AuthClientTwoLegged(FORGE_CLIENT_ID, FORGE_CLIENT_SECRET, SCOPES);
const appPackageApi = new ForgeSDK.AppPackagesApi();
const getToken = () => {
return oAuth2TwoLegged.authenticate();
};
const getUploadURL = () => {
return appPackageApi.getUploadUrl(oAuth2TwoLegged, oAuth2TwoLegged.getCredentials());
};
const patchPackage = (id, url) => {
const appPack = {
Resource: url,
RequiredEngineVersion: APP_PACKAGE_REQUIRED_ENGINE
};
return appPackageApi.patchAppPackage(id, appPack, oAuth2TwoLegged, oAuth2TwoLegged.getCredentials());
};
(async () => {
try {
const token = await getToken();
const url = await getUploadURL();
const patchPackRes = await patchPackage(APP_PACKAGE_ID, url);
if (patchPackRes.statusCode == 201)
console.log('Patch package succeeded!');
else
console.log('Patch package failed!' + patchPackRes.statusCode);
} catch (ex) {
console.log('Exception :(');
console.log(ex);
}
})();
When calling PATCH the "Resource" property must be set. It can be set to the same URL as the one you receive from GET but it must be present and valid.
This should work:
const ForgeSDK = require('forge-apis');
const oAuth2TwoLegged = new ForgeSDK.AuthClientTwoLegged(FORGE_CLIENT_ID, FORGE_CLIENT_SECRET, SCOPES);
const appPackageApi = new ForgeSDK.AppPackagesApi();
const getToken = () => {
return oAuth2TwoLegged.authenticate();
};
const getUploadURL = async (id) => {
const app = await appPackageApi.getAppPackage(id, oAuth2TwoLegged, oAuth2TwoLegged.getCredentials());
return app.body.Resource;
};
const patchPackage = (id, url) => {
const appPack = {
Resource: url,
RequiredEngineVersion: APP_PACKAGE_REQUIRED_ENGINE
};
return appPackageApi.patchAppPackage(id, appPack, oAuth2TwoLegged, oAuth2TwoLegged.getCredentials());
};
(async () => {
try {
const token = await getToken();
const url = await getUploadURL(APP_PACKAGE_ID);
const patchPackRes = await patchPackage(APP_PACKAGE_ID, url);
if (patchPackRes.statusCode == 201)
console.log('Patch package succeeded!');
else
console.log('Patch package failed!' + patchPackRes.statusCode);
} catch (ex) {
console.log('Exception :(');
console.log(ex);
}
})();

Node.js + body-parser object format changes when it reaches backend

I'm trying to send an object inside an another object from React frontend to Node/express backend using jquery ajax. The problem the data is received at the backend, it no longer looks follows the syntax of an object. Instead, it looks something like this:
{ 'data[name]': 'test name',
'data[size][height]': '123',
'data[size][weight]': '50' }
Here is the front end ajax call...
lendItem(){
let id = "5af3348742afc60ab71d7d80"
$.ajax({
url: '/api/items/' + id,
method: 'put',
data: {
'data': {
name: "test name",
size: {
height: 123,
weight: 50
}
}
},
success: (res) => {console.log(res)}
});
}
backend server...
const express = require('express');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
// connect to mongodb
mongoose.connect('mongodb://localhost/promedical');
mongoose.Promise = global.Promise;
const app = express();
const port = process.env.PORT || 5000;
// parsing data that was received
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
// initialize routes
app.use('/api', require('./routes/api'));
// error handling
app.use((err, req, res, next)=>{
res.status(422).send({error: err.message});
});
app.listen(port, () => {
console.log(`Listening on port ${port}`)
});
...and here is the route I'm interested in.
router.put('/items/:id', (req, res, next)=>{
console.log(req.body);
res.send("success");
});
I think this problem might have something to do with that body-parser. Is is possible to send objects inside an object via jquery ajax and have it keep it's form once it reaches the backend? If not, should I just send all the data inside one object and then parse it at the backend?
It turns out that the object called 'data' becomes a string after the backend has accepted the ajax call. Is there any way to prevent this from happening? I need to store that object into a database as an object, not as a string.

How to read json file on disk using sails js api controller?

I am new to sails js, I have to read json file in a sails generated controller and process the data in it. If its, express I generally use jsonfile module like this in app.js
let jsonfile = require('jsonfile')
let file = '/tmp/data.json'
jsonfile.readFile(file, function(err, obj) {
console.dir(obj)
})
How to do the same in sails js controller?
Oh, It seems as same as in express. I just tried able to read the data like this. In my controller
module.exports = {
readJsonFile: function (req, res) {
const jsonfile = require('jsonfile');
var file = './assets/json/data.json';
jsonfile.readFile(file, function (err, obj) {
if (err) {
res.json({err: err});
}
console.dir(obj)
res.json({obj: obj});
})
}
};
and its working. Thanks.
You can also use the readFileSync to read the JSON file
module.exports = {
index: async function (req, res) {
var filePath = './data/students.json';
let rawdata = fs.readFileSync(filePath);
let data = JSON.parse(rawdata);
sails.log("data", data);
return res.view('pages/index.ejs', data);
},
};