nodeJS Convert Buffer to fs.ReadStream object - javascript

I'm saving an image file locally so I can ready it using fs.createReadStream() and append it to my FormData to send it to a REST api. Like this: (I'm using the trello api https://developer.atlassian.com/cloud/trello/rest/#api-cards-id-attachments-post)
const fetch = require('node-fetch');
const Jimp = require('jimp');
const FormData = require('form-data');
// Save file locally
await Jimp.read(imagePNGURL).writeAsync(savedImagePath);
// Append it to the formdata using fs.createReadStream
const formData = new FormData();
formData.append('file', fs.createReadStream(savedImagePath));
// Send formData to api and image gets saved correctly
await fetch('TrelloUrl', { method: 'POST', body: formData })
Now I want to do the same thing but without saving the file locally but by using the image buffer. I've tried the following but I can't seem to make it work:
const fetch = require('node-fetch');
const Jimp = require('jimp');
const FormData = require('form-data');
const stream = require('stream');
// Save file to Buffer
const buffer = await Jimp.read(imagePNGURL).getBufferAsync('image/png');
// Convert buffer to stream
const bufferStream = new stream.PassThrough();
bufferStream.end(buffer);
// Try to append it to the formdata and send it to the api
const formData = new FormData();
formData.append('file', bufferStream); // Results in 400 Bad Request
formData.append('file', bufferStream.read()); // Results in empty image being uploaded
await fetch('TrelloUrl', { method: 'POST', body: formData })
---------
// Also tried to convert the buffer to stream like this:
const { Readable } = require('stream');
const bufferToStream = (buffer) => {
const stream = new Readable();
stream.push(buffer);
stream.push(null);
return stream;
};
formData.append('file', bufferToStream(buffer)); // Results in 400 Bad Request
formData.append('file', bufferToStream(buffer).read(); // Results in empty image being uploaded
How can I convert the buffer correctly to a fs.ReadStream() object so I can send it successfully to the api?
Or are there better ways to approach this?
All help is appreciated.

You can get the stream directly from the url using axios and append to form-data
const axios = require("axios")
const getImageStream = async (url) => {
const response = await axios.get(url, {responseType : "stream"});
if (response.status === 200) {
return response.data
}
}
const formData = new FormData();
formData.append('file', await getImageStream(imagePNGURL) );

set custom filename (set whatever name do you want) and content-type, worked for me
const formData = new FormData();
formData.append('file', bufferStream, {filename: 'photo.png', contentType: 'image/png');

Related

Push Data Into Array in State Array In Reactjs

Hello All I hope All Are Doing Well
I have A issue I am uploading multiple images in Cloudinary via ReactJs
Here Is Input Field
<input
type="file"
className="form-control"
required
onChange={(e) => setImages(e.target.files)}
multiple
/>
OnChange I'm storing all files on a state given below
const [images, setImages] = useState([]);
Now I am looping the state and uploading each file to Cloudinary and extracting the URL of each Image code is given below
for (const file of images) {
async function upload() {
const formData = new FormData();
formData.append("file", file);
formData.append("upload_preset", "DummyPreset"); // Replace the preset name with your own
formData.append("api_key", "0300545648961"); // Replace API key with your own Cloudinary key
// Make an AJAX upload request using Axios (replace Cloudinary URL below with your own)
await axios
.post(
"https://api.cloudinary.com/v1_1/Dummycloud/image/upload",
formData,
{
headers: { "X-Requested-With": "XMLHttpRequest" },
}
)
.then((response) => {
const data = response.data;
const fileURL = data.secure_url; // You should store this URL for future references in your app
console.log(fileURL);
});
}
upload();
}
Here I'm able to extract each link As fileURL and consoled it
console.log(fileURL);
To See The Output Please click the Link it will redirects you to the image Outputimage
As You Can see all URLs Are Extracted Now I want to push All Extracted URLs into an Array And Wants to send them to Express Server where I'll store them into DB
Please Let Me Know How Store All URLs into a state array whenever any URL extracted it'll be stored into That array
Here's The Solution
Thanks For Contribution
var ImagesUrlArray = [];
for (const file of image) {
async function upload() {
const formData = new FormData();
formData.append("file", file);
formData.append("upload_preset", "DummyPreset"); // Replace the preset name with your own
formData.append("api_key", "0300545648961"); // Replace API key with your own Cloudinary key
// Make an AJAX upload request using Axios (replace Cloudinary URL below with your own)
await axios
.post(
"https://api.cloudinary.com/v1_1/Dummycloud/image/upload",
formData,
{
headers: { "X-Requested-With": "XMLHttpRequest" },
}
).then((response) => {
const data = response.data;
var fileURL = data.secure_url; // You should store this URL for future references in your app
ImagesUrlArray = [...ImagesUrlArray];
ImagesUrlArray.push(fileURL);
if (ImagesUrlArray.length === image.length) {
const res = axios
.post("http://localhost:5000/register", {
fullname: Data.fullname,
email: Data.email,
pass: Data.pass,
cpass: Data.cpass,
phone: Data.phone,
imagee: ImagesUrlArray,
})
.then((response) => response);
setdataa(res);
}
});
}
upload();
}
// this function returns a Promise
const uploadFile = (file) => {
const formData = new FormData();
formData.append(stuff);
return axios.post('some/path', formData).then(response => response.data.secure_url);
};
Promise.all(images.map(uploadFile)).then(fileURLs => storeFileURLs(fileURLs))

Save FormData to Indexdb

The below code is what take final action to save the data to the target DB.
const onFileUpload = (e) => {
const files = Array.from(e.target.files);
const formData = new FormData();
formData.append('attachable_type', attachableType);
formData.append('attachable_id', attachableId);
if (files.length > 0) {
const file = files[0];
formData.append('file', file);
upload(dispatch, {
body: formData,
}).then(() => {});
}
};
Now I am building an offline app, where when no internet is available I would like to save this request to indexdb. I have the whole setup. All I want to know how can I save a FormData instance to indexdb so that I can later fetch it from indexdb and send it to server for permanent storage. I need some ideas. I tried some google but I don't see any direct answer to the following question. I am using idb npm plugin. The below update function I will be using to as an interface to talk to the db.
export async function update(attrs) {
const db = await createAppDB();
const tx = db.transaction('attachments', 'readwrite');
const store = tx.objectStore('attachments');
store.put(attrs);
await tx.done;
}
You could extract the FormData through the Body.formData() method, and then retrieve its content by getting this FormData's entries and store these to IDB:
(async () => {
// in ServiceWorker while disconnected
const request = buildRequest();
// extract the FormData
const fd = await request.formData();
const serialized = {
url: request.url,
method: request.method,
mode: request.mode,
body: [ ...fd ]
// you may need more fields from request
};
// you can now store the entries in IDB
// here we just log it
console.log( "stored", serialized );
// and to build back the Request
const retrieved = { ...serialized };
const new_body = new FormData();
for( let [ key, value ] of retrieved.body ) {
new_body.append( key, value );
}
retrieved.body = new_body;
const new_request = new Request( retrieved );
// fetch( new_request );
// remember to remove from IDB to avoid posting it multiple times
console.log( "sent", [...new_body] );
} )();
// returns the same kind of Request object a ServiceWorker would intercept,
// whose body is a FormData
function buildRequest() {
const fd = new FormData();
fd.append( "some-key", "some-data" );
fd.append( "the-file", new Blob( [ "hey" ] ), "file.txt" );
return new Request( "", { method: "POST", body: fd } );
}
Too bad we can't just put POST requests in the Cache API, it would have been a lot cleaner...
As far as I know, you cannot store any FormData into IndexedDB directly. In my case, I had to implement photo uploading for an offline app. I saved images into IndexedDB in base64 format with some other data and then uploaded them on the server once the internet connection is restored.

how to send files and data with axios in react? [duplicate]

This question already has answers here:
How to post a file from a form with Axios
(9 answers)
Closed 2 years ago.
backend is expecting something like
{
"key" : "xyz"
}// and two files
I've tried the following code, but it always shows empty params passed in url
const obj = {
key : [this.state.key]
};
const json = JSON.stringify(obj);
const blob = new Blob([json], {
type: 'application/json'
});
const data = new FormData();
data.append("params", blob);
data.append("data1",this.state.file1)
data.append("data2",this.state.file2)
let res= await axios.get(url,data);
console.log(res)
You can't send data(body) by using get method. I think you need to use post method.
const obj = {
key : [this.state.key]
};
const json = JSON.stringify(obj);
const blob = new Blob([json], {
type: 'application/json'
});
const data = new FormData();
data.append("params", blob);
data.append("data1",this.state.file1)
data.append("data2",this.state.file2)
let res= await axios.post(url,data);
You cannot use formData with get, in order to send with body, file upload has to be a post request.
let res= await axios.post(url,data);

Save Blob to FileSystem in React Native Expo

I am trying to download a PDF and share it via the 'expo-sharing' SDK. I can't use FileSystem.createDownloadResumable because the document is available via a POST request.
Download it as a blob and use FileReader to convert it to a base64 string to pass to FileSystem.writeAsStringAsync
const response = await axios.post(URL_PDF_CONTENT, { Benefits: payload }, { responseType: 'blob' });
const fr = new FileReader();
fr.onload = async () => {
const fileUri = `${FileSystem.documentDirectory}/pdf.pdf`;
await FileSystem.writeAsStringAsync(fileUri, fr.result.split(',')[1], { encoding: FileSystem.EncodingType.Base64 });
Sharing.shareAsync(fileUri);
};
fr.readAsDataURL(response.data);

How to post original file as formdata using api with filestack in reactjs?

I am using filestack in react to upload files. First i browse the images and upload it, on
Upload Done i am using a function, in this function i want to post original file as formdata
using my api with post method. So help me to post original file to my server after getting
response from filestack upload.
const options = {
maxFiles: 5,
onUploadDone: handleUploadFunction // callback function on upload done
};
const filestack = client.init("key", options);
const picker = filestack.picker(options);
function handleUploadFunction(result, board_id) {
const fileData = result.filesUploaded[0];
console.log(result);
const getValue = sessionStorage.getItem("user_id");
const token = sessionStorage.getItem("userToken");
let imageData = new FormData();
imageData.append("v_code", "1.0");
imageData.append("apikey", "41bbf547d64c309749b613f16323b762");
imageData.append("token", token);
imageData.append("userid", getValue);
imageData.append("board_id", 362);
imageData.append("img_text", "Test Image 362");
imageData.append("img_data", "image data 362");
imageData.append("card_id", 8854);
imageData.append("image", fileData.originalFile);
axios.post("http://160.153.247.88:3000/add_file", imageData).then(res => {
console.log(res.data);
});
}

Categories

Resources