Nodejs download image - node.js

I'm trying to download an image from my server using request.
I've managed to download something but i get more data than the image.
function _download(uri, save_as, destination) {
let options = {
uri: uri,
timeout: 100000,
followAllRedirects: true
};
return new Promise(( _resolve,_reject) => {
let ext, filename, bar, total, downloaded, req;
req = request(options).on('response', (resp) => {
if (resp.statusCode === 200){
ext = _getFileType(resp.headers['content-type']);
filename = destination+'/'+save_as+ext;
var stream = fs.createWriteStream(filename)
resp.pipe(stream).on('error',function(err){
_reject(err);
}).on('finish',function(){
_resolve(filename);
});
} else {
_reject("unable to download image %s",uri);
}
}).on('error', function(err) {
console.log(err)
_reject(err);
})
});
}
My original url is in form of https://www.test.com/image/original/12345, my server than redirects with a 301 status to my s3 bucket where image is stored.
Unfortunately due to the url of the image i have to wait that for the response header content type to determinate what kind of image it's and use it to pipe the image.
Everything works quite as expected... but i get more data than what is stored in s3.
Does anyone have any suggestion ?

please refer to the link below
var fs = require('fs'),
request = require('request');
var download = function(uri, filename, callback){
request.head(uri, function(err, res, body){
console.log('content-type:', res.headers['content-type']);
console.log('content-length:', res.headers['content-length']);
request(uri).pipe(fs.createWriteStream(filename)).on('close', callback);
});
};
download('https://www.google.com/images/srpr/logo3w.png', 'google.png', function(){
console.log('done');
});
please visit this link
And this link also

Related

Node JS createWriteStream download image

I have the following code which downloads an image from a URL and then performs some action:
var file = fs.createWriteStream(local_file);
var request = https.get(file_link, function(response) {
var request_response = response.pipe(file);
request_response.on('finish', function(){}};
However when viewing the download image in a browser, I'm getting a whole page of random characters and texts, which seems like an encoding issue.
My question is, how do I download an image using Node JS with the correct encoding?$
Thanks!
You can try with this, using the request module.
var fs = require('fs'),
request = require('request');
var download = function(uri, filename, callback){
request.head(uri, function(err, res, body){
console.log('content-type:', res.headers['content-type']);
console.log('content-length:', res.headers['content-length']);
request(uri).pipe(fs.createWriteStream(filename)).on('close', callback);
});
};
download('https://www.google.com/images/srpr/logo3w.png', 'google.png', function(){
console.log('done');
});

nodejs resize and save image from remote server

node js resize and save image from remote server.
Hi,
How can I resize image without to save locally and then to save it.
when I run bellow code, I get error: "Error: Input buffer contains unsupported image format"
code:
var fs = require('fs');
var request = require('request');
var sharp = require('sharp');
function getImage()
{
request('https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png', function (err, res, body) {
var binary = Buffer.from(body.toString(), 'base64');
sharp(binary).resize(198, 110).toFile('test.jpg', (err, info ) =>
{
console.log('err: ', err);
console.log('info: ', info);
});
});
}
I found resolving for my question:
var resizer = sharp().resize(198, 110).toFile('test.jpg', (err, info) => {
console.log('err: ', err);
console.log('info: ', info);
});
request('https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png').pipe(resizer);
If you can make sure that https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png returns the image, you can try to pipe the response directly to sharp rather than converting response to base64 format & processing.
var resize = sharp(binary).resize(198, 110);
resize.on('error', function() {
//handle error
});
resize.on('finish', function() {
// done
});
request('https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png')
.pipe(process);
Update:
Removed .toFile('test.jpg'); part

Nodejs is not receiving any code from Flask app.

I am really new in node js and a little bit more experienced in flaks. I am trying to connect a nodejs backend with a flask api. Basically I am sending a file that was uploaded in the nodejs app for processing (converting to another format) to my flask app.
For sending the data I am using request. In this way:
app.post('/converttest', uploader.single('file'), function(req,res){
var file = req.file,
result = {
error: 0,
uploaded: []
};
flow.exec(
function() { // Read temp File
fs.readFile(file.path, this);
},
function(err, data) { // Upload file to S3
var formData = {
file: data,
};
requestPack.post({url:'http://127.0.0.1:5000/api/resource/converter', formData: formData});
},
function(err, httpResponse, body) { //Upload Callback
if (err) {
return console.error('upload failed:', err);
}
res.redirect('/console');
});
});
Then I am receiving the file for processing in the flask app, like:
#app.route('/api/resource/converter', methods = ['POST','GET'])
def converter_csv():
if request.method == 'POST':
f = request.form['file']
if not f:
abort(400)
print('-----Converting-------')
file = open("temp/converting.txt","w")
file.write(f)
#....conversion process...
# Finish the process
return Response(converted_file,status=200)
In my console for the localhost of the flask app, I am getting:
127.0.0.1 - - [09/Aug/2017 15:47:59] "POST /api/resource/converter HTTP/1.1" 200 -
However my nodejs app did not receive any response. It just got frozen.
I appreciate any orientation anyone can give me. Thanks.
I think flow.exec is not in proper order
router.post('/converttest', uploader.single('file'), function(req, res) {
var filePath = req.file.path;
fs.readFile(filePath, 'utf8', function(err, data) { //change format reading as required
try {
formData = {file:data}
requestPack.post({url:'http://127.0.0.1:5000/api/resource/converter', formData: formData});
} catch(err) {
return console.error('upload failed:', err);
res.redirect('/console')
}
fs.unlink(filePath);}); });
I ended up using requestify. Seems like they make it a little bit easier for beginners like me:
var requestify = require('requestify');
app.get('/convertupload', function(req,res){
res.render('pages/convertupload');
});
app.post('/converttest', uploader.single('file'), function(req,res){
var file = req.file,
result = {
error: 0,
uploaded: []
};
flow.exec(
function() { // Read temp File
fs.readFile(file.path,this);
},
function(err, data) { // Upload file to S3
var formData = {
file: data
};
requestify.post('http://127.0.0.1:5000/api/resource/converter', {
form: formData
})
.then(function(response) {
// Get the response body (JSON parsed or jQuery object for XMLs)
console.log(response)
response.getBody();
});
res.redirect('/login');
});
});

upload binary file to redmine with node

I try to upload a file to redmine with node, I can upload and attach text files, but when I try to upload a binary file I get the token but the file doesn't work. I tried with json, xml and binary, ascii, base64 encoding.
I want upload binary files because I'm doing end to end test testing I want open Issues with screenshots, and upload a report.
I'm using node-rest-client for service calling
Could someone give me any suggestion to fix this problem?
Thanks,
I define the class RMClient
var Client = require('node-rest-client').Client;
var Q = require('q');
var RMClient = function(baseUri, apiToken){
this._apiToken = apiToken;
var client = new Client();
client.registerMethod('openIssue', baseUri+'/issues.json', 'POST');
client.registerMethod('uploadFile', baseUri+'/uploads.json', 'POST');
client.registerMethod('getIssues', baseUri+'/issues.json', 'GET');
this._client = client;
};
option 1:
var deferred = Q.defer();
var file fs.readFileSync(filePath);
//code for sending file to redmine uploads.json
return deferred.promise;
Option 2
var deferred = Q.defer();
var rs = fs.createReadStream(filePath, {'flags': 'r', 'encoding': null, 'autoClose': true});
var size = fs.statSync(filePath).size;
var file = '';
rs.on('error', function(err){
deferred.reject(err);
});
rs.on('data', function(chunk){ file += chunk; });
rs.on('end', function(){
//code for sending file to redmine uploads.json
});
return deferred.promise;
Code that I use to upload the file:
try{
if(!file){
throw new Error('File must\'nt be void');
}
var rmc = new RMClient(myRMURI, myAPItoken);
var headers = {
'X-Redmine-API-Key': rmc._apiToken,
'Content-Type': 'application/octet-stream',
'Accept':'application/json',
'Content-Length': size
};
var args = {
'data':file,
'headers': headers
};
if(parameters){
args.parameters = parameters;
}
rmc._client.methods.uploadFile(args, function(data, response){
if(response.statusCode != 201){
var err = new Error(response.statusMessage);
deferred.reject(err);
return;
}
var attach = JSON.parse(data);
console.log(attach);
if(data.errors){
var msg = ''.concat.apply('', attach.errors.map(function(item, i){
return ''.concat(i+1,'- ',item,(i+1<attach.errors.length)?'\n':'');
}));
console.error(msg);
deferred.reject(Error(msg));
}else{
deferred.resolve(attach.upload.token);
}
});
}catch(err){
console.error(err);
deferred.reject(err);
}
I faced the same issue and solved it this way:
Use "multer";
When you have an uploaded file, make a request using node "request" module, with req.file.buffer as body.
Then uploading files using the Rest API, you have to send the raw file contents in the request body, typically with Content-Type: application/octet-stream. The uploaded file doesn't need any further encoding or wrapping, esp. not as multipart/form-data, JSON or XML.
The response of the POST request to /uploads.xml contains the token to attach the attachment to other objects in Redmine.

Uploading images to S3 using NodeJS and Multer. How to upload whole file onFileUploadComplete

I'm using NodeJS and Multer to upload files to S3.
On the surface, everything appears to be working, the files get uploaded, and I can see them in the bucket when I log into the AWS console. However, most of the time when I follow the link to the file, the file is broken, often the file size is much smaller than the original file.
When the file reaches the server, the file size is correct if I log it, but on S3 it is much smaller. For example I just uploaded a file which is 151kb. The post request logs the file size correctly, but on S3 the file says it's 81kb.
Client side:
uploadFile = (file) ->
formData = new FormData()
formData.append 'file', file
xhr = new XMLHttpRequest()
xhr.open "POST", "/upload-image", true
# xhr.setRequestHeader("Content-Type","multipart/form-data");
console.log 'uploadFile'
xhr.onerror = ->
alert 'Error uploading file'
xhr.onreadystatechange = ->
if xhr.readyState is 4
console.log xhr.responseText
xhr.send formData
Server:
app.use(multer({ // https://github.com/expressjs/multer
inMemory: true,
limits : { fileSize:3000000 },
rename: function (fieldname, filename) {
var time = new Date().getTime();
return filename.replace(/\W+/g, '-').toLowerCase() + '_' + time;
},
onFileUploadData: function (file, data, req, res) {
var params = {
Bucket: creds.awsBucket,
Key: file.name,
Body: data,
ACL: 'public-read'
};
var s3 = new aws.S3();
s3.putObject(params, function (perr, pres) {
if (perr) {
console.log("Error uploading data: ", perr);
} else {
console.log("Successfully uploaded data", pres);
}
});
}
}));
app.post('/upload-image', function(req, res){
if (req.files.file === undefined){
res.end("error, no file chosen");
} else if (req.files.file.truncated) {
res.end("file too large");
} else {
console.log(req.files.file.size); //logs the correct file size
var path = creds.awsPath + req.files.file.name;
res.type('text/plain');
res.write(path);
res.end();
};
});
EDIT:
Setting file.buffer to the body perma onFileUploadComplete seems to work, but I have a feeling that this isn't the proper way of doing things, and may come back to bite me later. Is this approach okay, or are there issues I should be aware of doing this?

Resources