Saving an image from Node's readStream with client Javascript - javascript

I have been struggling with this one for a while now, and need your guys help! I am trying to streamline the process of downloading a report from my website. With node this is fairly straightforward with a readStream, like so:
router.post('/report', (req, res) => {
const filename = 'test.png';
const filePath = path.join(__dirname, filename);
fs.exists(filePath, exists => {
if (exists) {
const stat = fs.statSync(filePath);
res.writeHead(200, {
'Content-Type': 'image/png',
'Content-Length': stat.size,
'Content-Disposition': 'attachment; filename=' + filename,
});
fs.createReadStream(filePath).pipe(res);
} else {
res.writeHead(400, { 'Content-Type': 'text/plain' });
res.end('ERROR File does NOT Exists');
}
});
});
Now if I try this with Postman or some other API tester, it works perfectly, the file is downloaded and saved correctly. Now I am struggling to get this to work my front-end. I am currently running AngularJS and have tried to use FileSaver.js as a way to take this data and save it, however it never works. The file is saved, but the data is unreadable, aka the image previewer says the image is broken. I think I am creating the Blob incorrectly?
function exportReport(_id) {
this.$http
.post(
'/api/report',
{ _id },
{
headers: {
'Content-type': 'application/json',
Accept: 'image/png',
},
}
)
.then(data => {
console.log(data);
const blob = new Blob([data], {
type: 'image/png',
});
this.FileSaver.saveAs(blob, 'testing.png');
});
}
The console log result is as so:
Object {data: "�PNG
↵↵
IHDRRX��iCCPICC Profi…g�x #� #������Z��IEND�B`�", status: 200, config: Object, statusText: "OK", headers: function}
Am I suppose to decode the object.data?

Try adding responseType: 'blob' to the request and omit creating a new blob:
function exportReport(_id) {
this.$http
.post(
'/api/report',
{ _id },
{
headers: {
'Content-type': 'application/json',
Accept: 'image/png',
},
responseType: 'blob'
}
)
.then(data => {
console.log(data);
this.FileSaver.saveAs(data.data, 'testing.png');
});
}

Related

nodejs - AxiosError: Request failed with status code 500

I am trying to convert the below code which is using request module to axios module to send the POST request.
request module code:
const imageFile = fs.createReadStream('image.jpeg');
const imgName = "image" + ".jpeg";
var options = {
'method': 'POST',
'url': url,
'headers': {
'Content-Type': 'application/json',
'Cache-Control': 'no-cache',
'Accept': 'application/json'
},
formData: {
'image': {
'value': imageFile,
'options': {
'filename': imgName,
'contentType': null
}
}
}
};
request(options, function (error, response) {
if (error) throw new Error(error);
console.log("SUCCESS");
});
The above code works fine and the image is posted successfully with the request module. But when I convert the same to axios, I am getting a 500 Error. (AxiosError: Request failed with status code 500)
axios module code:
const FormData = require('form-data')
const imageFile = fs.createReadStream('image.jpeg');
const imgName = "image" + ".jpeg";
const bodyFormData = new FormData();
bodyFormData.append("image['value']", imageFile);
bodyFormData.append("image['options']['filename']", imgName)
// bodyFormData.append("image['options']['contentType']", null)
console.log(bodyFormData)
const formHeaders = bodyFormData.getHeaders();
axios.post(url, bodyFormData, {
headers: {
...formHeaders,
'Cache-Control': 'no-cache',
'Accept': 'application/json',
}
}).then(function (response) {
console.log('SUCCESS');
}).catch(function (error) {
throw new Error(error);
});
Can anyone find out what I am doing wrong here?
Is there any other way to post the image using axios other than using form-data?
See the documentation for FormData#append(). You can provide extra data like the file name as the 3rd options parameter
const bodyFormData = new FormData();
// Pass filename as a string
bodyFormData.append("image", imageFile, imgName);
// or to specify more meta-data, pass an object
bodyFormData.append("image", imageFile, {
filename: imgName,
contentType: "image/jpeg",
});
axios.post(url, bodyFormData, {
headers: {
Accept: "application/json",
"Cache-Control": "no-cache",
...bodyFormData.getHeaders(),
},
});
Under the hood, request() does something very similar with the exact same form-data library. See request.js

upload video to bunny stream with axios

i need to upload video to bunny stream :bunny docs
i convert file to base64 as thy do here: upload file: BODY PARAMS
if you select js axios as LANGUAGE you'll see the data value set in base64
and this is my code:
function UploadVideo(e){
const data = new FormData();
let file = e.target.files[0];
let video;
const toBase64 = file => new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result);
reader.onerror = error => reject(error);
});
async function Main() {
video = await toBase64(file);
}
Main();
const c_options = {
method: 'POST',
url: 'https://video.bunnycdn.com/library/49034/videos',
headers: {
Accept: 'application/json',
'Content-Type': 'application/*+json',
AccessKey: ''
},
data: '{"title":"test"}'
};
axios.request(c_options).then(function (c_response) {
//upload start
const u_options = {
method: 'PUT',
url: `https://video.bunnycdn.com/library/49034/videos/${c_response.data.guid}`,
headers: {
Accept: 'application/json',
AccessKey: ''
},
data: video,
};
axios.request(u_options).then(function (u_response) {
//post url to php
console.log(u_response.data);
}).catch(function (error) {
console.error(error);
});
//upload end
console.log(c_response.data);
}).catch(function (error) {
console.error(error);
});
}
but it return status code 400
The 400 error text: "Failed to read the request form. Form key length limit 2048 exceeded."
how can i do that?
The error is telling that a key is too long.
Your data property is meant to be an object, because axios default Content-Type (which you have omitted) is application/x-www-form-urlencoded.
If you want to send the file, then you need to set the Content-Type in you header to Content-Type: application/octet-stream, i.e. your header object should be
headers: {
Accept: 'application/json',
AccessKey: '',
Content-Type: 'application/octet-stream'
},
This shown in the javascript example on the bunny.net page you link to.

send image array for fetch formData in react-native

With the console.log I can see the array imagenes and this is ok in proyect react-native, but on the server this variable does not arrive but if I get the array of dates and the variable description on the server
let body = new FormData();
body.append('descripcion', 'dsadsadsa');
body.append('fechas[]', '2018-05-05');
body.append('fechas[]', '2015-05-05');
const {page1, page2, page3, page4, page5} = this.props.items;
body.append('imagenes[]', { uri: page2[2], name:'photo1.jpg', type: 'image/jpg'});
body.append('imagenes[]', { uri: page2[3], name:'photo2.jpg', type: 'image/jpg'});
body.append('imagenes[]', { uri: page2[4], name:'photo3.jpg', type: 'image/jpg'});
fetch(url, {
method: 'post',
headers: {
'Accept': 'application/json',
'Content-Type': 'multipart/form-data'
},
body: body
})
.then(res => res.text())
.then(res => {
console.log(res)
}).catch((err) => {
console.log('err', err)
});
});
Thanks for help me!
the code upload data and file (images) in RN this is ok, the bug in vars size file php.ini (memory_limit, upload_max_filesize, post_max_size).
in nginx, edit file nginx.conf add or update command
client_max_body_size 500M
Link https://www.cyberciti.biz/faq/linux-unix-bsd-nginx-413-request-entity-too-large/

WP REST API Media upload using fetch()

I'm trying to use fetch() to perform a media upload in WP Rest API using JS (React Native).
Here's what I've done so far:
fetch('https://www.example.fr/wp-json/wp/v2/media', {
method: 'post',
headers: new Headers({
'Content-Type': 'image/jpeg',
'Authorization': 'Basic d3GtcmVzdC1sdfGktY2xpZW50Onefepbl9hdh90aWJldA==',
'Content-Disposition': 'attachment; filename="user-'+userId+'.jpg"'
}),
body: imageBase64Data
})
.then(function (response) {
console.log(response);
});
imageBase64Data is set like this:
let imageBase64Data = 'data:image/png;base64,'+ imageData;
and imageData is react-native-image-picker response.data: https://github.com/react-community/react-native-image-picker#the-response-object
Here's my issue: the media is created successfully on my WP, but the image is empty (no data, around 15B). So I'm guessing something is messing up with the data I'm sending as the body of my request. But I don't know what.
Any ideas?
For the record, here's how I finally ended up with this issue, using react-native-fetch-blob module:
RNFetchBlob.fetch('post', 'https://www.example.fr/wp-json/wp/v2/media',
{
'Content-Type': 'image/jpeg',
'Authorization': 'Basic dqdsfqsdfpbl9hqsdfdsfWJldA==',
'Content-Disposition': 'attachment; filename="user-'+userId+'.jpg"'
}
,imageUri) // imageUri = RNFetchBlob.wrap(imageUri);
.then(function (response) {
console.log(response); // returns a 201 response with id of the attached media
});

Error when POST file multipart/form-data (JavaScript)

I got an error every time when trying to POST data to the API.
Request:
changeUserAvatar(authParam, file) {
let formData = new FormData();
//file is actually new FileReader.readAsDataURL(myId.files[0]);
formData.append('profile_image', file);
fetch(BASE_URL + 'profile-image', {
method: 'POST',
headers: {
'Content-Type': 'multipart/form-data',
'Authorization': authParam
},
body: formData
}).then((response) => {
return response.json();
}).then((response) => {
debugger;
}).catch((error) => {
console.error(error);
});
}
Error: profile_image can not be blank (422).
But it's not blank!
Request payload:
What do I do wrong?
Solved at GutHub: https://github.com/github/fetch/issues/505
I just had to leave Header without pointing any Content-Type manually.

Categories