I need to make this curl command into a nodejs request, either using fetch, request or axios networking libraries
The request needs to PUT the file data to the URL
curl -v -H "Content-Type:application/octet-stream" --upload-file C:/Users/deanv/Pictures/test3.mp4 "https://www.example.com/file/upload"
I've tried using CurlConverter to convert my curl command to node code, but this doesn't work as I cant add the file data.
var fetch = require('node-fetch');
fetch('https://www.example.com/file/upload', {
method: 'PUT',
headers: {
'Content-Type': 'application/octet-stream'
}
});
All help appreciated. Thanks in advance.
Try this:
// setup modules
const fetch = require('node-fetch');
const FormData = require('form-data');
const fs = require('fs');
const path = require('path');
// setup paths
const pathToFile = 'C:/Users/deanv/Pictures/test3.mp4';
const uploadUrl = 'https://www.example.com/file/upload';
// create form, 'content-type' header will be multipart/form-data
const form = new FormData();
// read the file as stream
const fileStream = fs.createReadStream(path.resolve(pathToFile));
// add the file to the form
form.append('my_file', fileStream);
fetch(uploadUrl, {
method: 'PUT',
body: form
}).then((res) => {
console.log('done: ', res.status);
return res.text();
})
.then((res) => {
console.log('raw response: ', res);
})
.catch(err => {
console.log('err', err);
});
Related
I m newbie who is learning to play with API. I m getting POST req error while using axios.
In docs of API which I want to interact, they give curl example.
curl -X POST https://ssuploader.streamsb.com/upload/01
-d "api_key=948324jkl3h45h"
-d "#path/filename.mp4"
-H "Content-Type: application/x-www-form-urlencoded"
I am trying to make that POST request using axios. I wrote simple script like this.
const axiosConfig = {
headers : {
"Content-Type": "application/x-www-form-urlencoded"
}
}
const file = __dirname + "/video/Video.mp4";
const fileData = fs.readFileSync(file);
const data = `api_key=${API_KEY}&${fileData}`;
axios.post('https://ssuploader.streamsb.com/upload/01', data, axiosConfig).then((result) => {
console.log(result.data);
}).catch((err) => {
console.log("Getting Error : ", err);
});
I am getting this error.
Getting Error : AxiosError: getaddrinfo ENOTFOUND ssuploader.streamsb.com
I m really new to interacting with API, so that I thought some of my structure was wrong while converting curl to axios. I really don't know what to do. I mean I can't figure out my false. Can anyone help me? Thank you so much.
Some Changes
I figure out some of my false with the help of answers. I forget to GET the server first. So that I updated my code to this.
const file = __dirname + "/video/Video.mp4";
const fileData = fs.createReadStream(file);
const formData = new FormData();
formData.append('file', fileData);
formData.append('api_key', API_KEY);
console.log(formData)
axios.get(`https://api.streamsb.com/api/upload/server?key=${API_KEY}`).then(result => {
const url = result.data.result;
axios.post(url, formData, axiosConfig)
.then((result) => {
console.log(result.data);
}).catch((err) => {
console.log("Getting Error : ", err);
});
})
But I am getting new Error.
AxiosError: Request failed with status code 400
As I understand from the documentation this is 2 step process. At first you need to get the upload URL (server as they call it) and then use it to upload your file.
So use something like this:
axios.get(`https://api.streamsb.com/api/upload/server?key=${API_KEY}`).then((result) => {
const url = result.data.result;
// your post request to this url here
}).catch((err) => {
console.log("Getting Error : ", err);
});
You are sending fileData as a string in the data Object
Use 'Content-Type': 'multipart/form-data'instead of using "Content-Type": "application/x-www-form-urlencoded"
Code will be like this
import FormData from 'form-data';
const axiosConfig = {
headers: {
'Content-Type': 'multipart/form-data'
}
}
const file = __dirname + "/video/Video.mp4";
const fileData = fs.createReadStream(file);
const formData = new FormData();
formData.append('file', fileData);
formData.append('api_key', API_KEY);
axios.post('https://ssuploader.streamsb.com/upload/01', formData, axiosConfig)
.then((result) => {
console.log(result.data);
}).catch((err) => {
console.log("Getting Error : ", err);
});
If you have any query, you can ask
It's them, not you.
There is no DNS record for ssuploader.streamsb.com (you can enter it into https://mxtoolbox.com/DNSLookup.aspx to check), which means that when you try to connect to it, it leads nowhere.
Unless you do some digging and find a domain from them that has a DNS record, there isn't anything you can do.
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)
}
}
MRE -> node-server : react app
When I send a POST request using Postman, I get the expected result. This is the request that I am sending using Postman
and test sent gets printed to the console of my node server
If I send a request from my react form however, test sent does not print to the console, but the catch block of my fetch request get's executed and err is printed to the console of my react app, followed by {}.
I would like to know why my POST request is not working and is not getting received by the server
Below is the function that I call when someone clicks the submission button of my form created in react
Function called on form submission
nodeUrl = 'https://localhost:6060?'
const submitData = async () => {
fetch(nodeUrl, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({'test': 'test'})
}).then((res) => {
alert('then')
}).catch((err) => {
alert('err')
alert(JSON.stringify(err))
})
}
}
This is the server that I run using node server.js
server.js
server.post('/', function(req, res) {
console.log('test sent')
mailer.messages().send(req.body)
.then((mes) => {
console.log(mes)
res.json({ message: 'Thanks for your message. Our service team has been notified and will get back to you shortly.' })
}).catch(err => {
console.log(err)
res.json(err);
})
});
The majour issue here is due to CORS. CORS support can be used to overcome this. Just keep in mind to have this only for development mode(see below codes).
But, as per the Postman's snapshot and provided GitHub repositories, the request from Front-end should be of multipart/form-data type. Thus, the Front-end code would look like this
const nodeUrl = "http://localhost:6060/";
const submitData = async () => {
// create a FormData object
const formData = new FormData();
formData.append('form', 'example#email.com');
formData.append('to', 'example#email.com');
// this auto adds 'multipart/form-data' + HASH header in the request
fetch(nodeUrl, {
method: "POST",
body: formData
})
.then(res => {
console.log(res);
}).catch(err => {
console.log('Error -', err);
});
};
To handle multipart/form-data request in the ExpressJS, you need a plugin Multer.
const express = require('express');
const bodyParser = require('body-parser');
const multer = require('multer'); // for 'multipart' type request
const server = express();
const upload = multer();
// allow CORS requests in development mode
if (process.env.NODE_ENV === 'development') {
// Server run command - "NODE_ENV=development node server.js"
const cors = require('cors');
server.use(cors());
}
server.use(bodyParser.json());
server.use(bodyParser.urlencoded({extended: true}));
// using Multer middleware form extracting 'FormData' payload
server.post('/', upload.none(), function(req, res) {
console.log('Received body', req.body);
... // other codes
});
Strategy 2(plain JSON) -
If that 'multipart/form-data' strategy was unintentional and you just want to send simple JSON, use below codes -
In Front-end, trigger API request as -
fetch(nodeUrl, {
method: "POST",
headers: {
'Content-Type': 'application/json', // this needs to be defined
},
body: JSON.stringify({ from: 'some#email.com', to: 'other#email.com' })
})
In server, just ignore codes related to Multer and only keep your API as -
server.post('/', function(req, res) {
console.log('Received body', req.body);
... // other codes
});
I ended up using a better fetch request, which was put together for me by selecting code -> Javascript Fetch in Postman(under the save button)
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/x-www-form-urlencoded");
var urlencoded = new URLSearchParams();
urlencoded.append("from", "example#email.com");
urlencoded.append("test", "test");
var requestOptions = {
method: 'POST',
headers: myHeaders,
body: urlencoded,
redirect: 'follow'
};
fetch("http:localhost:6060/, requestOptions)
.then(response => {
if (response.ok){
response.json().then(json => {
console.log(json)
})
}
})
.catch(error => console.log('error: ', error))
I am using an existing API call to send a file to our cloud provider via Nodejs. I have seen several different methods of doing this online, but figured I would stick to using "fetch" as most of my other API calls have been using this as well. Presently, I keep getting 500 internal server error and am not sure why? My best conclusion is that I am not sending the file properly or one of my pieces of formdata are not resolving correctly. See the below code:
const fetch = require("node-fetch");
const formData = require("form-data");
const fs = require("fs");
var filePath = "PATH TO MY FILE ON SERVER WITH FILE NAME";
var accessToken = "Bearer <ACCESS TOKEN>;
var url = '<API URL TO CLOUD PROVIDER>';
var headers = {
'Content-Type': 'multipart/form-data',
'Accept': 'application/json',
'Authorization': accessToken
};
const form = new formData();
const buffer = fs.readFileSync(filePath);
const apiName = "MY_FILE_NAME";
form.append("Content-Type", "application/octect-stream");
form.append("file", filePath);
console.log(form);
fetch(url, { method: 'POST', headers: headers, body: form })
.then(response => response.json())
.then(data => {
console.log(data)
})
.catch(err => {
console.log(err)
});
This my first time attempting something like this so I am next to certain I am missing something. Any help with getting me in the right direction is appreciated.
So the issue was exactly what I mentioned above. The code was not uploading the file I specified. I finally figured out why and below is the modified code which will grab the file and upload to our cloud service provide:
const fetch = require("node-fetch");
const formData = require("form-data");
const fs = require("fs");
var apiName = process.env['API_PATH'];
var accessToken = "Bearer" +" "+ process.env['BEARER_TOKEN'];
var url = process.env['apiEnv'] +"/" +"archive";
var headers = {
'Accept': 'application/json',
'Authorization': accessToken,
};
const form = new formData();
const buffer = fs.readFileSync(apiName);
const uploadAPI = function uploadAPI() {
form.append("Content-Type", "application/octet-stream");
form.append('file', buffer);
fetch(url, {method: 'POST', headers: headers, body: form})
.then(data => {
console.log(data)
})
.catch(err => {
console.log(err)
});
};
uploadAPI();
Being new to Javascript/Nodejs I wasn't really sure what the "buffer" variable did. After finally figuring it out I realized I was adding too many body form params to the request and the file was not being picked up and sent to the provider. All code above is using custom variables, but if for whatever reason someone wants to use it, then simply replace the custom variables with your own....Thanks again for any and all assistance....
import fs from 'fs'
import FormData from 'FormData';
const fileStream = fs.createReadStream('./file.zip');
const form = new FormData();
form.append('key', fileStream, 'file.zip');
const response = await axios.post(url, form, {
headers: {
...form.getHeaders(),
},
});
Im trying to read a file (image) from amazon S3 and post it to another server with multipart/form.
let imageParams = { Bucket: 'my-bucket', Key: 'imageName.jpg' };
let formData = new FormData();
formData.append('file', s3.getObject(imageParams).createReadStream());
let apiResponse = await api.post("/fileUpload", formData,
{ params: { token: process.env.API_TOKEN } },
{ headers: {'Content-Type': 'multipart/form-data' } } );
But im not managing it to work, it returns me:
Error: Request failed with status code 415
maybe im misunderstanding how the createReadStream() works?
Use concat for pipe the stream. Otherwise form data send only the first chunk of stream, and the server don't know how to handle it.
For example
const axios = require('axios');
const {S3} = require('aws-sdk');
const FormData = require('form-data');
const s3 = new S3();
var concat = require('concat-stream')
const api = axios.default.create({
baseURL: 'http://example.com',
})
const readStream = s3.getObject({Bucket: 'bucket', Key: 'file'}).createReadStream();
readStream.pipe(concat(filebuffer => {
const formData = new FormData();
formData.append('file', filebuffer);
formData.getLength((err, length) => {
console.log(length)
const headers = formData.getHeaders({'content-length': length})
console.log({headers})
return api({
method: 'post',
url: "/upload",
headers: headers,
data: formData
})
})
}))