Read content of posted .txt file with Azure function NodeJS - node.js

I want to know the content from a .txt file I upload via the JSON response with an Azure function. I'm able to read the filename and type, but also want to convert the file to a string in my JSON response. But currently the response in data stays empty:
{
"name": "20200429112846_-_IB_records.txt",
"type": "text/plain",
"data": ""
}
My code is:
var multipart = require("parse-multipart");
module.exports = function (context, request) {
// encode body to base64 string
var bodyBuffer = Buffer.from(request.body);
var boundary = multipart.getBoundary(request.headers['content-type']);
// parse the body
var parts = multipart.Parse(bodyBuffer, boundary);
var fileContent = "";
var fileBuffer = Buffer.from(parts[0].data);
var fs = require('fs');
fs.readFile(fileBuffer, 'utf8', function(err, data) {
if (err) throw err;
fileContent = data;
});
context.res = { body : { name : parts[0].filename, type: parts[0].type, data: fileContent}};
context.done();
};
Anyone got an idea?

fs.readFile operates asynchronously, so
context.res = { body : { name : parts[0].filename, type: parts[0].type, data: fileContent}};
context.done();
is executed before the file has actually been read. One way to solve this is to put the context-stuff in the readFile callback:
fs.readFile(fileBuffer, 'utf8', function(err, data) {
if (err) throw err;
fileContent = data;
context.res = { body : { name : parts[0].filename, type: parts[0].type, data: fileContent}};
context.done();
});

Related

file upload not working in react native with multipart form data api nodejs

I am trying to upload image file with react native, by using nodejs multipart api, but the file is not getting sent from the FE. If I console req.files its undefined at server side. Here is my react native code:
var options = {
title: 'Select Image',
storageOptions: {
skipBackup: true,
path: 'images'
}
};
ImagePicker.showImagePicker(options, (response) => {
console.log('Response = ', response);
if (response.didCancel) {
console.log('User cancelled image picker');
} else if (response.error) {
console.log('ImagePicker Error: ', response.error);
} else if (response.customButton) {
console.log('User tapped custom button: ', response.customButton);
} else {
console.log('User selected a file form camera or gallery', response);
const data = new FormData();
data.append('name', 'avatar');
data.append('file', {
uri: response.uri,
type: response.type,
name: response.fileName
});
const config = {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'multipart/form-data',
},
body: data,
};
fetch("http://myapi.com/api/v1/user", config)
.then((checkStatusAndGetJSONResponse) => {
console.log(checkStatusAndGetJSONResponse);
}).catch((err) => { console.log(err) });
}
}
)
and Nodejs code:
const storage = multer.memoryStorage({
destination:(req, file, callback) => {
callback(null, '')
}
});
const upload = multer({ storage: storage }).array('file');
upload(req,res,(err) => {
if(err) {
console.log('ERROR: ',err);
return res.end("Error uploading file.");
}else{
console.log('REQUEST: ',req.files);
}
});
I am not able to upload image with some user data, please let me know what am doing wrong here
Thanks
as you are sending form data in body, it will only hold that form data.
if you want to send form data plus some other data, then try to append form data in another object and then append other data in same object with key value pair.
I have created user register form in which I have some input fields and profile upload.
For upload I have used "ngx-file-drop".
like:-
const body = {};
body['formData'] = formValues;
body['fileData'] = this.fileDataArray;
In this the ts code is like below.
dropped(files: NgxFileDropEntry[]) {
this.fileError = false;
this.files = [];
this.files = files;
for (const droppedFile of files) {
// Is it a file?
if (droppedFile.fileEntry.isFile && this.isFileAllowed(droppedFile.fileEntry.name)) {
this.filesArray.push(droppedFile);
const fileEntry = droppedFile.fileEntry as FileSystemFileEntry;
const formData: FormData = new FormData();
fileEntry.file((file: File) => {
});
fileEntry.file((file: File) => {
this.dropFilePath.push(droppedFile.relativePath);
// append form data
formData.append('upload', file, droppedFile.relativePath);
this.dropFile.push(file);
this.dropFileFlag = true;
});
} else {
// It was a directory (empty directories are added, otherwise only files)
const fileEntry = droppedFile.fileEntry as FileSystemDirectoryEntry;
this.dropFilePath = [];
this.dropFile = [];
this.files = [];
this.toaster.error('only this file are allowed : [".jpg", ".jpeg",".gif",".png"]', 'Error', {
positionClass: 'toast-top-full-width',
});
break;
}
}
}
and html code is.
<ngx-file-drop [disabled]="isPreview ? true : null" dropZoneLabel="Drop files here" (onFileDrop)="dropped($event)" (onFileOver)="fileOver($event)"(onFileLeave)="fileLeave($event)">
<ng-template ngx-file-drop-content-tmp let-openFileSelector="openFileSelector">
<span [attr.disabled]="isPreview ? true : null" class="btn">Drop files here or</span>
<span [attr.disabled]="isPreview ? true : null" (click)="openFileSelector()" class="btn btn-link">click to upload</span>
</ng-template>
</ngx-file-drop>
and on form submit you can do like this.
onSubmit() {
this.submitted = true;
if (this.form.invalid || (this.submitted && this.fileError)) {
this.toaster.error('Invalid form data..!!', 'ERROR');
return;
}
const formData = this.form.value;
this.fileDataArray.push(formData.getAll('upload'));
console.log('this.fileDataArray-------->', this.fileDataArray);
const body = {};
body['formData'] = formData;
body['fileData'] = this.fileDataArray;
console.log('body------>', body);
// call below your api function
}

How to download csv file with koajs

I'm using koajs as a framework for nodejs. I try to create csv data and response it to client but not working
let fields = ['code', 'status'];
let p = new Promise((resolve, reject) => {
json2csv({data: data, fields: fields }, (err, response) => {
if (err) {
reject(err);
} else {
resolve(response);
}
});
});
return p.then(data => {
let fileName = 'promotioncode-' + moment().unix();
ctx.response.attachment(fileName + '.csv');
ctx.response.type = 'application/ms-excel';
ctx.body = data;
})
The response is plan text data instead of attachment file
Here is response headers
Here is response body
If you would like to send a downloadable file attached to the body you need to create a read stream of the file.
const fs = require('fs');
ctx.set('Content-disposition', `attachment; filename=${result}`);
ctx.statusCode = 200;
ctx.body = fs.createReadStream(result);
Note: in result you have the file path
This worked for me:
ctx.set('Content-disposition', `attachment; filename=${fileName}.csv`);
ctx.statusCode = 200;
ctx.body = data;

Is it possible to send a file from a client to restler.file?

Normally restler.post() takes a restler.file(...) object to send a POST. This works if you have the file path on the server.
For example:
//#############################################################################
// Video upload from file system on node console server
//#############################################################################
function(done){
var fileStats = fs.statSync(videoFileName);
var fileSizeInBytes = fileStats["size"];
var data = {
'name': objectVideoName,
'type':'video',
'content': 'application/mp4',
'file': restler.file(videoFileName, null, fileSizeInBytes, null, "video" )
};
restler.post('https://api.astra.io/v0/bucket/'+bucketName+'/object', {
multipart: true,
data : data,
headers : { "Astra-Secret": astraSecret }
}).on('complete', function(response) {
console.log('Upload video to bucket: \n', response);
done(null);
});
},
How can I POST the file from the client directly without saving it on the server?
I'm trying with busboy.
//#############################################################################
// Video upload from client then POST to cdn
//#############################################################################
app.post('/addVideo', function (req, res) {
var video = {};
var busboy = new Busboy({headers: req.headers});
busboy.on('file', function (fieldname, file, filename, encoding, mimetype) {
var ext = mimetype.split('/').pop();
var token = generateToken(crypto);
var fileSizeInBytes = 900000;
filename = token + ext;
var videoName = filename;
var bucketName = 'sampleVideos';
var data = {
'name': videoName,
'type':'video',
'content': 'application/mp4',
'file': ***** WHAT GOES HERE ******
};
restler.post('https://api.astra.io/v0/bucket/'+bucketName+'/object', {
multipart: true,
data : data,
headers : { "Astra-Secret": astraSecret }
}).on('complete', function(response) {
console.log('Upload video to bucket: \n', response);
res.send("200");
});
});
busboy.on('field', function (fieldname, val, fieldnameTruncated, valTruncated) {
video[fieldname] = val;
});
busboy.on('finish', function () {
console.log('busboy finished');
});
req.pipe(busboy);
});
There are two helper functions exported by restler to help create your data options. You don't use either and specify a JS Object literal. restler.data() is what you want to use
data: function(filename, contentType, data) {
return new Data(filename, contentType, data);
}
So instead of
var data = {
'name': videoName,
'type':'video',
'content': 'application/mp4',
'file': ***** WHAT GOES HERE ******
};
in your example you would do this as it allows you to use arbitrary content instead of a file name
var data = restler.data(videoName, 'application/mp4', file);

How to get write unencoded html to a file?

I'm using reading in a .HTML snippet from the file system; it contains just <h1>Hulton Archive</h1>. Then I'm writing a new XML file which must contain that HTML snippet in a certain element. using XMLbuilder to build an XML file out of it. Here's what I have:
var fs = require('fs');
var xml2js = require('xml2js');
var builder = new xml2js.Builder();
var parseString = require('xml2js').parseString;
var result;
var inputFile = "html-snippet.html";
var outputFile = "test.xml";
fs.readFile(inputFile, "UTF-8", function (err, data) {
if (err) {
return console.log(err);
}
console.log(data);
var obj = {name: "Super", Surname: "Man", age: data};
var outputXML = builder.buildObject(obj);
fs.writeFile(outputFile, outputXML, function(err) {
if(err) {
console.log(err);
} else {
console.log(outputFile + " was saved!");
}
});
});
The problem is that the HTML tags are encoded in the input file; changed from <h1>header</h1> into <h1>header</h1>. I want to preserve the HTML tags instead of encoding them in the output file.
I have tried writing this file using both XMLbuilder (https://github.com/oozcitak/xmlbuilder-js) and xml2js (https://github.com/Leonidas-from-XIV/node-xml2js). It seems like both of them were encoding the HTML on the output file.
How can I get write out the XML file without encoding the HTML?
Using npm install ent you can decode the HTML after you generate the XML. This does generate "invalid" XML however. For most people, CDATA is probably the better choice.
var fs = require('fs');
var xml2js = require('xml2js');
var builder = new xml2js.Builder();
var parseString = require('xml2js').parseString;
var decode = require('ent').decode;
var result;
var inputFile = "html-snippet.html";
var outputFile = "test.xml";
fs.readFile(inputFile, "UTF-8", function (err, data) {
if (err) {
return console.log(err);
}
console.log(data);
var obj = {name: "Super", Surname: "Man", age: data};
var outputXML = decode(builder.buildObject(obj));
fs.writeFile(outputFile, outputXML, function(err) {
if(err) {
console.log(err);
} else {
console.log(outputFile + " was saved!");
}
});
});

how to upload base64 data as image to s3 using node js?

I am sending base64data of canvas to node.js script. I need the base64data to be stored as an image to the s3bucket. Is there any way to achieve it?
Store your Data URI in a variable.
Create function which decodes your data URI(64 bit encoded string) to string(Here I have created dataURItoBlob() function) and after decoding return the string.
Pass that string to in body of S3 upload function.
var myDataUri = "data:image/jpg;base64,JVBERi0xLjMKMyAwIG9iago8PC9UeXBlIC9QYW..."
var myFile=dataURItoBlob(myDataUri);
function dataURItoBlob(dataURI) {
var binary = atob(dataURI.split(',')[1]);
var array = [];
for (var i = 0; i < binary.length; i++) {
array.push(binary.charCodeAt(i));
}
return new Blob([new Uint8Array(array)], {
type: 'image/jpg'
});
}
if (myFile)) {
results.innerHTML = '';
var params = {
Key: fileName+'.jpg',
ContentType: 'image/jpg',
Body: myFile
};
bucket.upload(params, function(err, data) {
results.innerHTML = err ? 'ERROR!' : 'UPLOADED.: ' + file;
});
} else {
results.innerHTML = 'Nothing to upload.';
}
you can send base64 data with AWS putObject method as follows
var AWS = require('aws-sdk');
AWS.config.loadFromPath('./s3_config.json');
var s3Bucket = new AWS.S3( { params: {Bucket: 'myBucket'} } );
var imageBase64Data='Your base64 code '
s3Bucket.putObject(imageBase64Data, function(err, data){
if (err) {
console.log(err);
console.log('Error uploading data: ', data);
} else {
console.log('succesfully uploaded the image!');
}
});

Resources