Uploading File via API Using NodeJS 'fetch' - javascript

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

Related

AxiosError: getaddrinfo ENOTFOUND

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.

CURL Command to NodeJS - PUT Request OctetStream

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

issue in react code for sending data to multer

I was trying to send image to backend(multer) I checked multiple times the backend code seems correct,is there a issue in my front end code ? POST code snippet
const response = await fetch('http://localhost:5000/api/users/signup',{
method:'POST',
headers:{
'Content-Type': 'application/json'
},
body:JSON.stringify({
name: data.get('name'),
email: data.get('email'),
password: data.get('password'),
image:data.get('image')
})
});
full auth.js code https://pastebin.com/MHdDRtAX
I think you'd want to use FormData object.
const input = document.querySelector('input[type="file"]');
const body = new FormData();
body.append('image', input.files[0]);
body.append('name', data.get('name'));
body.append('email', data.get('email'));
body.append('password', data.get('password'));
// add more items as needed
const response = await fetch(URL, { method:'POST', body });
You have a content type mismatch. When using multer, you need use 'Content-Type': 'multipart/form-data'.
The basic idea is to use the FormData object.
Example below
const data = new FormData(event.target)
const response = await fetch('http://localhost:5000/api/users/signup',{
method:'POST',
headers:{
'Content-Type': 'multipart/form-data'
},
body: data
});
In network tab you will find form data with key-value
image should be a file(binary)
in multer, example code like below
var express = require('express')
var multer = require('multer')
var upload = multer({ dest: 'uploads/' })
var app = express()
app.post('api/users/signup', upload.single('image'), function (req, res, next) {
// req.file is the `image` file
// req.body will hold the text fields, if there were any
})

Read file from Amazon S3 with nodeJS and post it to another server with axios

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

Upload Excel File from React to C# ASP.NET Core backend

I am trying to upload a file from a react front end to a C# backend. I am using drop zone to get the file and then I call an api helper to post the file but I am getting different errors when I try different things. I am unsure exactly what the headers should be and exactly what I should send but I get two distinct errors. If I do not set the content-type I get 415 (Unsupported Media Type) error. If I do specify content type as multipart/form-data I get a 500 internal server error. I get the same error when the content-type is application/json. The url is being past in and I am certain it is correct. I am unsure if the file should be appended as file[0][0] as I have done or as file[0] as it is an array but I believe it should be the first. Any suggestions welcome :) Here is my api post helper code:
export const uploadAdminFile = (file, path, method = 'POST', resource =
config.defaultResource) => {
const url = createUrl(resource, path);
const data = new FormData();
data.append('file', file[0][0]);
data.append('filename', file[0][0].name);
const request = accessToken =>
fetch(
url,
{
method,
mode: 'cors',
withCredentials: true,
processData: false,
headers: {
Accept: 'application/json',
'Content-Type': 'application/json', //'multipart/form-data',
Authorization: `Bearer ${accessToken}`,
},
body: data,
})
.then(res => res.json())
.then(success => console.log('API HELPER: file upload success: ', success)
.catch(err => console.log('API HELPER: error during file upload: ', err)));
return sendRequest(request, resource);
};
Thanks for the help and suggestions, it turned out to be a backend issue but even still I learned a lot in the process. I will post my working code here in case anyone comes across this and finds it useful.
export const uploadAdminFile = (file, path, resource=config.defaultResource) => {
const url = createUrl(resource, path);
const formData = new FormData();
formData.append('file', file[0][0]);
formData.append('filename', file[0][0].name);
const request = accessToken =>
fetch(url,
{
method: 'POST',
headers: {
Accept: 'application/json',
Authorization: `Bearer ${accessToken}`,
},
body: formData,
});
return sendRequest(request, resource);
};
As mentioned, the file name does not need to be sent separately and count be omitted. I am indexing the file this way because I get it from dropzone as an array and I only want a single file (the first one in the array). I hope this helps someone else out and here is a link to the mdn fetch docs (good information) and a good article on using fetch and formData.

Categories

Resources