Node js file upload issue - node.js

I'm trying to upload a file to nanosets API. I uploaded the following node js function to firebase and trying to excess it with following URL for example with a file in body (trying to test this with postman)
Node js function looks like:
exports.uploadFile = functions.https.onRequest((req, res) => {
cors(req, res, () => {
if (req.method !== "POST") {
return res.status(500).json({
message: "Not allowed"
});
}
const busboy = new Busboy({headers: req.headers});
let uploadData = null;
busboy.on("file", (fieldname, file, filename, encoding, mimetype) => {
const filepath = path.join(os.tmpdir(), filename);
uploadData = {modelId: '4bc54977-60cf-4415-a417-c39f1c18b83f', file: fs.createReadStream(filename), type: mimetype};
const options = {
url: 'https://app.nanonets.com/api/v2/OCR/Model/XXXXXXX-60cf-4415-a417-c39f1c18b83f/LabelFile/',
formData: uploadData,
headers: {
'Authorization': 'Basic ' + Buffer.from('tiOJNxuDbdl40lXXXXXXXXXXFTYbY' + ':').toString('base64')
}
};
request.post(options, function (err, httpResponse, body) {
if (err) {
console.log(err);
}
console.log(body)
});
});
busboy.on("finish", () => {
res.status(200).json({
message: "It worked!"
});
});
busboy.end(req.rawBody);
});
});
Why I check the logs with firebase functions:log I get the following results:
2020-06-06T09:35:06.168774140Z D uploadFile: Function execution started
2020-06-06T09:35:06.344Z I uploadFile: invoice_4.pdf
2020-06-06T09:35:06.432Z I uploadFile: FileStream {
2020-06-06T09:35:06.439Z E uploadFile: TypeError: source.pause is not a function
Anyone an idea? How to pass the file to nanosets?

In order to make outgoing requests from Cloud Functions, your project must be on the Blaze payment plan.

Related

File download from mongodb atlas to client(react js) using node js

I am a beginner in Reactjs and Nodejs. I am trying to download a file(.pdf,.jpg) from mongodb atlas in react using node js. I have used createReadStream method from Gridfs to fetch the data at server, need to send this data as a file to react so that user can download it when required. But can't get the file at client side.
FileServer.js
app.use('/download', (req, res) => {
// Check file exist on MongoDB
var filename = req.query.filename;
console.log(req.body.filename);
gfs.exist({ filename: req.body.filename ,"root": "uploads"}, (err, file) => {
console.log(file);
if (err || !file) {
console.log("error")
res.status(404).send('File Not Found');
return
}
res.setHeader('Content-Type', 'application/octet-stream');
res.setHeader('Content-Disposition', 'attachment; filename="'+req.body.filename+'"');
var str='';
var readstream = gfs.createReadStream({ filename: req.body.filename });
readstream.pipe(res);
});
});
FileClient.js
onSubmitDownload(e){
e.preventDefault();
axios.post("http://localhost:3000/file_server/download", {filename:'MyFile.pdf'})
.then(res => res.data).then(res=>this.setState({
msg:res
}));
}
Unable to take response in file format
The trick was in getting the response in the format we want, here we need to receive the data in file format. So the code at client side using Filesaver is
onSubmitDownload(e){
e.preventDefault();
axios({
method: "GET",
url: "http://localhost:8000/download",
responseType: "blob"
}).then(response => {
this.setState({ fileDownloading: true }, () => {
FileSaver.saveAs(response.data, data1);
console.log(response);
});
})
.then(() => {
this.setState({ fileDownloading: false });
console.log("Completed");
});
}
you can also check https://github.com/ANS-Developers113/File-Upload-Download-Application

Can't unit test a working file upload with node/express

I am trying to unit test a node/express upload file.This is my first piece of work tying node.I could get the job done in the frontend but hen I had to test it,it went downhill... The file gets uploaded on both frontend and when unit testing but I get an error of res.json is not a functionmostly because I change the CVS to a JSON file in writeFile.
I tried to change the unit test a fair amount of time but I think I am stuck.I've changed the file parameter the attach parameter etc...
test.js
var request = require("supertest");
const app = require('../routes/file');
describe('/upload file', () => {
it('Should upload a file', (done) => {
request(app).post('/upload',function(err,res){
console.log('asdasdasd');
done();
})
.set('Content-Type', 'multipart/form-data')
.set('Accept', 'application/json')
.attach('file', "testdata.csv")
.end(function(){
});
});
file.js
router.post('/upload',function(req, res) {
upload(req, res, function (err) {
let filePath = req.file.path;
let fileExtension = path.extname(filePath);
if (err instanceof multer.MulterError || fileExtension !== '.csv') {
return res.status(500).json(err);
} else if (err || fileExtension !== '.csv') {
return res.status(500).json(err);
}
CSVToJSON({
headers: ['id', 'name', 'age', 'address', 'team'],
noheader: true,
}).fromFile(filePath).then(source => {
helpers.writeFile('data',filePath,source,res);
});
});
});
helpers.js
writeFile(fileName,filePath,source,res){
if (fs.existsSync(filePath)) {
fs.writeFile(`../public/files/${fileName}.json`,JSON.stringify(source),'utf-8',function (err) {
if (err) {
return res.json({"error" : true, "message" : err,'status':500});
} else {
return res.json({"error" : false, "message" : "File Uploaded Successfuly",'status':200});
}
});
}
}
I expected a status of 200 and res.json to be defined.

How to stream file as download on Loopback 4?

I'm trying to create a system that would read a file from another site and serve this as a file download to the user. The file size could vary from Mbs to Gbs.
I have have already created a proof of concept using vanilla nodejs.
const app = express();
app.get('/', (req, res) => {
res.setHeader('Content-disposition', 'attachment; filename=FILENAME');
res.setHeader('Content-type', 'application/octet-stream');
http.get('URL_TO_FILE', data => {
data.pipe(res);
});
});
I would like to do this using loopback 4. Is this possible? Thanks!
You can do this easily with nodejs request and using the loopback 4 controllers.
You need to import this packages:
var request = require('request');
var fs = require('fs');
And put this code in the endpoint method:
#get('/getImage')
async retrieveImage(): Promise<any> {
let file = fs.createWriteStream(__dirname + `/file.jpg`);
console.log('the file is here: ' + file.path);
return await new Promise((resolve, reject) => {
request({
url: 'URL_TO_FILE',
headers: {
'Content-disposition': 'attachment; filename=FILENAME',
'Content-type': 'application/octet-stream',
},
gzip: true,
})
.pipe(file)
.on('finish', () => {
console.log(`The file is finished downloading.`);
resolve();
})
.on('error', (error: any) => {
reject(error);
})
}).catch(error => {
console.log(`something happened: ${error}`)
});
}
From this you need to go to this url:
http://localhost:3000/getImage
And the file would be in your controllers folder with the "file.jpg" name.

NodeJS String to Buffer pdf file

Hi guys i'm trying to download a pdf file and save it on my disk. The API send me a string. But the following code not working.
axios.get('https://myapi.com/download', config).then((res) => {
var buff = Buffer.from(res.data, 'binary');
fs.writeFile('file.pdf', buff, function (err) {
if (err) throw err;
console.log('Saved!');
});
}).catch((e) => {
console.log(e);
})
I've tried it, and working ...
fs.readFile('./download.pdf','binary', function (err, data) {
var str = data.toString();
var buff = Buffer.from(str, 'binary');
fs.writeFile('novopdf.pdf',buff, () => {
console.log('ok');
})
});
You need to config axios get request as follows
const response = await Axios({
method: 'GET',
url: url,
responseType: 'stream'
})
response.data.pipe(Fs.createWriteStream(path)) // path is location where you want to write the file.
Then check for end event on the response object.

writing file from post request in ExpressJS

Working with express to create a file transfer tool, and I've almost gotten everything completed. Just need to figure out how to get the data from the request written to file.
My issue appears to be stemming from not knowing where the file contents are placed in the request object.
My code to process sending the request
let file = watcher.getOneFile(config.thisLocation);
console.dir(file);
let contents = fs.readFileSync(file.fullPath, 'utf-8');
console.log(contents);
let form = {
attachments: [
contents
]
}
rq.post({
url: `http://${homeAddress}:${port}/files/?loc=${config.thisLocation}&file=${file.fileName}`,
headers: {'content-type':'application/x-www-form-urlencoded'},
formData: form
}, (err, res, body) => {
// body = JSON.parse(body);
console.log(body);
});
and when I get the request on the server, I'm not sure where the file contents actually are.
Code for handling the request
app.post('/files', (req, res) => {
console.log(req.query.loc);
// console.dir(req);
let incoming = watcher.getOutputPath(req.query.loc, config.locations);
console.log(incoming);
console.dir(req.body);
// console.log(req.body);
// let body = JSON.parse(req.body);
console.log(req.query);
let filename = path.join(incoming, req.query.file);
console.log(filename);
fs.writeFile(filename, req.body, (err) => {
if(err){
console.error(err);
}
console.log(`Successfully wrote file: ${path.join(incoming, req.query.file)}`);
});
res.sendStatus(200);
});
Where on the Request Object is the file contents?
Unfortunately you can't access the file content in any straightforward way. I recommend you to use busboy or similar package to parse form-data requests.
Here is how can you read file content using busboy and write it to the file system:
const Busboy = require('busboy');
app.post('/files', (req, res) => {
const busboy = new Busboy({ headers: req.headers });
busboy.on('file', (fieldname, file, filename, encoding, mime) => {
const newFilename = `${Date.now()}_${filename}`,
newFile = fs.createWriteStream(newFilename);
file.pipe(newFile);
file.on('end', () => {
console.log(`Finished reading ${filename}`);
});
});
busboy.on('finish', () => {
console.log('Finished parsing form');
res.sendStatus(200);
});
req.pipe(busboy);
});

Resources