HTTP POST with a file upload - javascript

I am new to javascript/protractor and am trying to write code that posts or uploads a text file to a REST endpoint, somewhat, on the following lines. I am not able to get this to work and do not know why it is failing. Can anyone please validate this or suggest a better solution, preferably with sample code. (I have checked online and found lot of information, but was not able to apply any of that directly.)
var request = require('request');
var fs = require('fs');
var path = require('path');
var form = new FormData();
form.append('agency', 'California');
form.append('siteType', 'EF');
fileName = "test.txt";
var filePath = path.resolve(__dirname, "../resources/upload/" + fileName);
fs.writeFileSync(filePath,
"This is a test txt file");
form.append('file', fs.createReadStream(absolutePath));
request.post({url: restServiceUrl, formData: form},
function optionalCallback(err, httpResponse, body) {
if (err) {
console.error('upload failed:', err);
}
console.log('Upload successful! Server responded with:', body);
});

Related

Upload images to a Node.JS server without using <form>

I have a node.js server, which uses express-fileupload to accept images. Now I'm working on the function to upload an image. But I don't want to use < form > since I prefer xhtml request for various reasons, but mainly because I don't want to redirect the user, after he uploads an image.
I have tried reading the picture as dataURI, sending it to the server, decoding it and writing it to a file, which didnt work and seemed to resource intensive and laborious.
//I used the dataString from the callback method and wrote it to a file using fs.writeFile
function dataURItoimage(dataString, callback){
const atob = require("atob");
dataString.replace("data:image/jpeg;base64,", "");
dataString.replace("data:image/png;base64,", "");
atob(dataString);
callback(null, dataString);
}
//User side code
avatarInput.addEventListener("change", (e) => {
const reader = new FileReader();
reader.readAsDataURL(avatarInput.files[0]);
reader.onload = () => {
avatar = reader.result;
tosend.avatar = reader.result;
}
}, false);
uploadButton.onclick = () => {
var request = new XMLHttpRequest();
request.open("POST", "/avatarUpload");
request.setRequestHeader("Content-Type", "application/json");
var tosend = {avatar: ""};
tosend.avatar = avatar;
request.send(JSON.stringify(tosend));
}
Is there a better way to upload an image, which the user can select, to a node.js server?
You can try this example. It worked for me. I hope it can help you.
Sending dataURL throw Ajax request:
const dataURL = snapshotCanvas.toDataURL('image/png');
$.ajax({
url: 'http://localhost:3000/upload-image',
dataType: 'json',
data: { data: dataURL },
type: 'POST',
success: function(data) {}
});
Receiving request:
router.post('/', (req, res) => {
const base64 = req.body.data.replace(/^data:image\/png;base64,/, "");
fs.writeFileSync(`uploads/images/newImage.jpg`, base64, {encoding: 'base64'});
}
So I did it this way:
var request = new XMLHttpRequest();
request.open("POST", "/test");
var fd = new FormData();
fd.append("file", avatarInput.files[0]);
request.send(fd);
I created a FormData Object, appended the image, which the user chose in an input called "avatarInput", and send the object to the server.
On server side I used express-fileupload to access the file:
app.post("/test", (req, res) => {
if(req.files){
//With the follwing command you can save the recieved image
req.files.file.mv("./file.png", (err) => {if(err)throw err});
}
res.end();
});

Nodejs error encoding when get external site's content

I used get method of request module to get content of external site. If encoding of external site is utf-8, it is ok, but it has display error with other encodings such as shift-jis
function getExternalUrl(request, response, url){
mod_request.get(url, function (err, res, body) {
//mod_request.get({uri: url, encoding: 'binary'}, function (err, res, body) {
if (err){
console.log("\terr=" + err);
}else{
var result = res.body;
// Process res.body
response.write(result);
}
response.end();
});
}
How can I get content of external site with correct encoding?
I found the way to do:
Get with binary encoding
var mod_request = require('request');
mod_request.get({ uri: url, encoding: 'binary', headers: headers }, function(err, res, body) {});
Create a Buffer with binary format
var contentBuffer = new Buffer(res.body, 'binary');
Get real encoding of page by detect-character-encoding npm
var mod_detect_character_encoding = require('detect-character-encoding');
var charsetMatch = mod_detect_character_encoding(contentBuffer);
Convert page to utf-8 by iconv npm
var mod_iconv = require('iconv').Iconv;
var iconv = new mod_iconv(charsetMatch.encoding, 'utf-8');
var result = iconv.convert(contentBuffer).toString();
P/S: This way is only applied for text file (html, css, js). Please do not apply for image file or others which is not text

Download image from express route

I have an express server running with the following route:
exports.getUserFile = function (req, resp) {
let filePath = path.join(__dirname, 'storage', req.params.fileName);
resp.download(filePath);
});
}
In my web app i'm calling this route and trying to save the file locally using file-saver:
let req = request.get('/users/' + userId + '/files/' + file.name);
req.set('Authorization', 'Bearer ' + this.state.jsonWebToken);
req.end((err, resp) => {
let f = new File([resp.text], file.name, {type: resp.type});
fileSaver.saveAs(f);
});
If the file is plain text then it works ok, but for other file types like images i'm not able to open the file (it's 'corrupt').
This is what the response looks like:
Do I need to decode the data in some way first? What is the correct way to save the content of the file?
If you're using superagent to perform the requests, you can explicitly set the response type to "blob", which would prevent any attempts to decode the response data. The binary data will end up in resp.body:
req.responseType('blob').end((err, resp) => {
saveAs(resp.body, file.name);
});
I haven't used express for a long time ago and I'm typing from mobile, it's seems a encoding issue, so it's seems that you're a sending raw image, you will need to encode it in base64 try something like:
//Here your saved file needs to be encoded to base 64.
var img = new Buffer(data, 'base64');
res.writeHead(200, {
'Content-Type': 'image/png',
'Content-Length': img.length
});
res.end(img);
Where data is your saved image, If you can render the image you just add the headers for download or just chain method download.
If you want to download the image as attachment in the page you can use res
exports.getUserFile = function (req, resp) {
let filePath = path.join(__dirname, 'storage', req.params.fileName);
var check = fs.readFileSync(__dirname+req.params.fileName);
resp.attachment(req.params.fileName); // The name of the file to be saved as. Eg Picture.jpg
res.resp(check) // Image buffer read from the path.
});
}
Reference:
http://expressjs.com/en/api.html#res.attachment
http://expressjs.com/en/api.html#res.end
Hope this helps.

How to download a file from node server(using only node modules, no express, etc)

Im currently writing a handler for a download feature. When the user clicks on the download button from his\her browser the download handler is called, which will then initiate the download(mp3 files only). I had this working on php, but I have since changed everything on my project to Node and I can't seem to get this last part working on Node.
This is the php code I had working before:
<?php
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=".($_GET['title']));
readfile($_GET['path']);
?>
This is the the new code for Node:
function download(response, request){
var body = [];
request.on('data', function(chunk) {
body.push(chunk);
});
request.on('end', function() {
body = Buffer.concat(body).toString();
var data = qs.parse(body);
var title = data.songTitle;
var filePath = __dirname + "/../myproject/songs/"+title+".mp3";
fs.open(filePath,'r',function(err, fd){
if(!err){
fs.readFile(fd, function(err, data){
if(!err){
var rs = fs.createReadStream(filePath);
response.writeHead(200, {"Content-Type": "application/octet-stream",
"Content-Disposition": "attachment; filename="+title+".mp3",
"Content-Length" : data.length});
rs.pipe(response);
response.on("end",function(){
fs.close(fd);
});
}else{
console.log("Error while trying to read: ", err);
}
});
}else{
console.log("Error could not open: ", err);
}
});
});
When trying to download, I do not get any errors but nothing happens. I have also tried "audio/mpeg3" for content-type, and nothing. Any ideas on what's going on? I'm trying to do this without using third-party modules.
Please note that the function download in not passed as the callback function of http.createServer(). So the order of response and request is not the issue :)
It looks like you switched request and response. Also, instead of using fs.open()/fs.readFile() to determine file size, you can use fs.stat(), which should be much more resource-friendly (since it doesn't require loading the entire file into memory first):
function download(request, response) {
var body = [];
request.on('data', function(chunk) {
body.push(chunk);
});
request.on('end', function() {
var data = qs.parse(Buffer.concat(body).toString());
var title = data.songTitle;
var filePath = title + '.mp3';
fs.stat(filePath, function(err, stats) {
if (err) {
response.statusCode = 500;
return response.end();
}
response.writeHead(200, {
"Content-Type" : "application/octet-stream",
"Content-Disposition" : "attachment; filename="+title+".mp3",
"Content-Length" : stats.size,
});
fs.createReadStream(filePath).pipe(response);
});
});
}

Downloading Mp3 file from remote. Node js

I am trying to download a mp3 file from the remote url using node js. For that I am using the following code. But It doesn't work (File that downloading having 0 bytes only its not playing once it downloaded).
var http = require('http');
var fs = require('fs');
var url = "http://play.publicradio.org/rivet/d/podcast/marketplace/segments/2015/09/28/mp_20150928_seg_01_64.mp3";
var dest = "2.mp3";
var file = fs.createWriteStream(dest);
var request = http.get(url, function(response) {
console.log("res "+response);
response.pipe(file);
file.on('finish', function() {
console.log("File download Completed");
});
}).on('error', function(err) { // Handle errors
});
The problem here is that http doesn't follow redirects.
You can use the request npm module that does it by default to avoid handling headers yourself.
var fs = require('fs'),
request = require('request');
request
.get('http://foo.com/bar.mp3')
.on('error', function(err) {
// handle error
})
.pipe(fs.createWriteStream('2.mp3'));

Categories