I am using "Axios" to call a WCF method that takes as parameter file information and content.
The file is read and sent as a base64 encoded string.
My issue is that when the file size exceeds a certain limit, AXIOS throws an exception: "Error: Request body larger than maxBodyLength limit".
I looked up the issue and found that all solutions suggest increasing the maxContentLength / maxBodyLength parameters in the AXIOS configuration object, but did not succeed.
Find Below an implemented test case in node.js:
var axios = require('axios');
var fs = require('fs');
var path = require('path')
var util = require('util')
let readfile = util.promisify(fs.readFile)
async function sendData(url,data) {
let params = data
let resp = await axios({
method: 'post',
url: url,
data: JSON.stringify(params),
headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' }
// maxContentLength: 100000000,
// maxBodyLength: 1000000000
}).catch(err => {
throw err;
})
return resp;
}
async function ReadFile(filepath) {
try{
let res = await readfile(filepath,'base64')
let filename = path.basename(filepath).split('.').slice(0, -1).join('.')
let ext = path.extname(filepath)
return {data:res,fext:ext,fname:filename}
let x = 1
}
catch(err)
{
throw err
}
}
(async () => {
try {
let img = await ReadFile('Files/1.pdf')
let res = await sendData('http://183.183.183.242/EMREngineEA/EMRWS.svc/web/EMR_TestUploadImg',img)
console.log(res)
}
catch (ex) {
console.log(ex)
}
}
)();
In my case, the pdf file is 20 MB, upon running, an error is thrown.
"Error: Request body larger than maxBodyLength limit"
I tried to setting the maxContentLength: 100000000, maxBodyLength: 1000000000
as presented above, but did not succeed.
Your help is appreciated.
The maxBodyLength seems to work for me in this simple test, I upload data to a local Express server. If I try to upload more than the maxBodyLength I get the same error you're getting. So I suspect there's something more, like a redirect happening in your case that's triggering the error.
There is an issue logged for axios here that seems to reference the problem, it suggests setting maxContentLength to Infinity (as the other commenter suggests).
e.g.
maxContentLength: Infinity,
maxBodyLength: Infinity
Test code below:
const axios = require("axios");
function generateRandomData(size) {
const a = Array.from({length: size}, (v, k) => Math.floor(Math.random()*100));
return { data: a, id: 1 };
}
async function uploadData(url, size) {
let params = generateRandomData(size);
let stringData = JSON.stringify(params);
console.log(`uploadData: Uploading ${stringData.length} byte(s)..`);
let resp = await axios({
method: 'post',
url: url,
data: stringData,
headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' },
maxContentLength: 100000000,
maxBodyLength: 1000000000
}).catch(err => {
throw err;
})
console.log("uploadData: response:", resp.data);
return resp;
}
uploadData("http://localhost:8080/upload", 10000000);
Corresponding server code:
const express = require("express");
const port = 8080;
const app = express();
const bodyParser = require('body-parser')
app.use(bodyParser.json({limit: '50mb'}));
app.post('/upload', (req, res, next) => {
console.log("/upload: Received data: body length: ", req.headers['content-length']);
res.json( { status: 'ok', bytesReceived: req.headers['content-length']});
})
app.listen(port);
console.log(`Serving at http://localhost:${port}`);
Related
I've been trying to send a JSON data using fetch but the backend receives an empty object.
In my Client JS I have
const user = "company1";
const username = "muneeb";
const data = {user, username};
fetch("http://127.0.0.1:3000/users/api/login", {
method: 'POST',
body: JSON.stringify(data)
}).then((response) => {
console.log(response);
});
The server side has:
router.post('/users/api/login', async (req, res, next) => {
try {
// console.log(request.body);
const request = JSON.stringify(req.body);
let imageTitles = [];
console.log(request);
*its random from here on out but you get the idea*
await components.getImages(imageTitles);
const finalKey = imageTitles.join("");
let images = await components.output(req.body.user ,req.body.username);
res.send(components.jsonConverter(imageTitles, images)); //---Top priority
db.setPassword(req.body.user, req.body.username , finalKey);
} catch (err) {
console.log(err);
res.send(err).sendStatus(500);
};
})
A few things I have already tried :
It works perfectly in Insomnia(postman).
express.json() is present , it helped me go from undefined to blank JSON.
I have enabled cors settings.
That's it for now.
The body parser express.json will only be applied for requests with Content-Type: application/json. You have to add the content type to your fetch call:
fetch("http://127.0.0.1:3000/users/api/login", {
method: 'POST',
body: JSON.stringify(data),
headers: {
'Content-Type': 'application/json'
}
})
I am trying to make POST request with axios but getting 400 bad request error message. I tried same request in POSTMAN but it worked correctly any idea what I am missing?
Code:
const TWITTER_UPLOAD_MEDIA_BASE_URL = 'https://upload.twitter.com/1.1/media/upload.json';
const url = "https://ik.imagekit.io/XXXXXXXXXXXX/test-upload_XXXXXXXXXXX.png";
const { data } = await axios.get(url);
const form = new FormData();
form.append('media', data);
const token = {
key: oauth_access_token,
secret: oauth_access_token_secret
};
const oauth = OAuth({
consumer: {
key: process.env.TWITTER_CONSUMER_KEY,
secret: process.env.TWITTER_CONSUMER_SECRET
},
signature_method: 'HMAC-SHA1',
hash_function: (baseString, key) => crypto.createHmac('sha1', key).update(baseString).digest('base64')
});
const authHeader = oauth.toHeader(oauth.authorize({
url: `${TWITTER_UPLOAD_MEDIA_BASE_URL}?media_category=tweet_image`,
method: 'POST'
}, token));
const result = await axios.post(`${TWITTER_UPLOAD_MEDIA_BASE_URL}?media_category=tweet_image`, form, {
headers: {
Authorization: authHeader["Authorization"],
'Content-type': "multipart/form-data",
"Content-Transfer-Encoding": "base64"
}
});
I also tried:
const url = "https://ik.imagekit.io/XXXXXXXXXXXX/test-upload_XXXXXXXXXXX.png";
const image = await axios.get(url, { responseType: 'arraybuffer' });
const raw = new Buffer.from(image.data).toString('base64');
const base64Image = "data:" + image.headers["content-type"] + ";base64," + raw;
const token = {
key: oauth_access_token,
secret: oauth_access_token_secret
};
const oauth = OAuth({
consumer: {
key: process.env.TWITTER_CONSUMER_KEY,
secret: process.env.TWITTER_CONSUMER_SECRET
},
signature_method: 'HMAC-SHA1',
hash_function: (baseString, key) => crypto.createHmac('sha1', key).update(baseString).digest('base64')
});
const authHeader = oauth.toHeader(oauth.authorize({
url: `${TWITTER_UPLOAD_MEDIA_BASE_URL}?media_category=tweet_image`,
method: 'POST'
}, token));
const result = await axios.post(`${TWITTER_UPLOAD_MEDIA_BASE_URL}?media_category=tweet_image`, {media_data: base64Image}, {
headers: {
Authorization: authHeader["Authorization"],
'Content-type': "multipart/form-data",
"Content-Transfer-Encoding": "base64"
}
});
Bot snippets not working.
Till line 27 (first code snippet) everything is correct. Issue is from line 28 with axios and form content
POSTMAN screenshots of successful request:
I think axios has got some serious issues:
https://github.com/mzabriskie/axios/issues/789
https://github.com/axios/axios/issues/1006
https://developer.twitter.com/en/docs/twitter-api/v1/media/upload-media/api-reference/post-media-upload
Twitter media upload guide: https://developer.twitter.com/en/docs/twitter-api/v1/media/upload-media/uploading-media/media-best-practices
firstly download your image like:
const url = 'https://url-to-your-image'
const { data } = await axios.get(url, {
responseType: 'stream',
})
after that you can append the image directly in formdata
const formData = new FormData()
formData.append('media', stream)
and finally upload
const result = await axios.post(`${TWITTER_UPLOAD_MEDIA_BASE_URL}?
media_category=tweet_image`, formData, {
headers: {
Authorization: authHeader["Authorization"],
'Content-type': "multipart/form-data",
"Content-Transfer-Encoding": "base64"
}
});
If you still get a problem let me know
I'm building a web application that requires to me to receive file binaries on a server-side endpoint, convert those binaries to FormData, then POST them to another endpoint. The second endpoint only accepts "multipart/form-data".
I'm using axios to create the requests, and NodeJS on the server.
The files are posted from the client as form data, but I'm unable to manipulate them as such once they reach the server.
How do I compel file binaries to FormData in my server-side scripts?
Client:
const handleImageSubmit = async (attachments) => {
try {
let image
if (attachments.length) {
const formData = new FormData()
for (let i = 0; i < attachments.length; i += 1) {
formData.append(
`files.${attachments[i].name}`,
attachments[i],
attachments[i].name
)
}
const config = {
headers: { 'Content-Type': 'multipart/form-data' },
}
image = await axios.post(
'/api/proxy/upload',
formData,
config
)
}
console.log('Files dispatched to server')
} catch (err) {
console.error(err)
}
}
Server-side:
const upload = async (req, res) => {
try {
const data = new FormData()
// Convert the binaries in req.body into FormData
const myFiles = ...
data.append('files',
myFiles)
const config = {
method: 'post',
url: `${process.env.API_URL}/upload`,
headers: {
Authorization: `Bearer ${req.headers['auth-token']}`,
...data.getHeaders()
},
data: data,
}
const signal = await axios(config)
res.json(signal.data)
} catch (err) {
console.error(err)
res.status(fetchResponse?.status || 500).json(err)
}
}
I am fetching IGDB api on server because I need to go through CORS. I am using async await connected to client side. Everything works fine but I need to pass query like '/?fields=cover.*,name;limit=50;' to https://api.igdb.com/v4/games from client side, not from server. When I am adding a query to client side, it's still showing the query only from server. How I can pass this query from client side? This is my code:
api/example.js
import Cors from "cors";
import initMiddleware from "../../components/init-middleware";
const cors = initMiddleware(
Cors({
methods: ['GET', 'POST', 'OPTIONS'],
})
)
const settings = {
method: 'POST',
headers: {
'Accept': 'application/json',
'Client-ID': 'my_client-id',
'Authorization': 'Bearer my_authorization',
},
}
const remoteServerUrl = 'https://api.igdb.com/v4/games'
export default async function handler(req, res) {
await cors(req, res)
const response = await fetch(remoteServerUrl, settings);
const data = await response.json()
res.json(data)
}
client side
const settings = {
method: 'POST',
headers: {
'Accept': 'application/json',
'Client-ID': 'my_client-id',
'Authorization': 'Bearer my_authorization',
},
const fetchData = async () => {
let query = '/api/example/'
const response = await fetch(query + HERE I WANT TO ADD QUERY, settings);
const data = await response.json();
}
Edit:
Status Code: 308 Permanent Redirect
initMiddleware
// Helper method to wait for a middleware to execute before continuing
// And to throw an error when an error happens in a middleware
export default function initMiddleware(middleware) {
return (req, res) =>
new Promise((resolve, reject) => {
middleware(req, res, (result) => {
if (result instanceof Error) {
return reject(result)
}
return resolve(result)
})
})
}
So I am building a recipe search engine and I want to transfer the user's choice of the category to the server so I can use it in API call. Here's some code :
CLIENT-SIDE
function getRecipes(category){
const categorySearch = category.alt;
let data = {
categoryChoice: categorySearch
}
console.log(data);
let options = {
method: 'POST',
headers: {
'Content-type': 'text/plain'
},
body: JSON.stringify(data)
}
const promise = fetch('/data', options);
console.log(promise);
}
SERVER-SIDE
const express = require('express');
const app = express();
const fetch = require('node-fetch');
require('dotenv').config();
const API_KEY = process.env.API_KEY;
const port = process.env.PORT || 3000;
app.listen(port, () => console.log('listening at 3000'));
app.use(express.static('public'));
app.use(express.json({ limit: "1mb"}));
app.post('/data', (request, response) => {
let data = request.body;
console.log(data);
response = "Got data";
console.log(response);
})
categorySearch and data variables definitely get what it should, I have logged in and it's working fine. Then whether I log promise in client-side or data in server-side I only get {}, any ideas?
Working with JSON content type.
Backend-Side should be returning data:
app.post('/data', (request, response) => {
let data = request.body;
let gotData;
if(data.categoryChoice == "option1")
gotData = {id:1, label:"val 1", q:data.categoryChoice};
else
gotData = {id:2, label:"val 123", q:data.categoryChoice};
response.json(gotData);
});
And the Client-Side:
let data = { categoryChoice: "option1" };
let options = {
method: 'POST',
headers: {
"Content-type": "application/json; charset=UTF-8"
},
body: JSON.stringify(data)
}
const promise = fetch('/data', options);
promise.then(response => {
if (!response.ok) {
console.error(response);
} else {
return response.json();
}
}).then(result => {
console.log(result);
});
Your backend part should be returning a response for it to work the way you expect it.
You are only handling a POST request but you also need a get request.
app.get('/data', (request,response) => {
return response.json({
// JSON data here
})
})