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

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.

Related

Upload file using mutler without disabling bodyparser in NEXTJS

I am trying to upload an image file using mutler along with some form data. Every solution I've looked suggests to disable the bodyparser but if I disable the body parser then I cannot parse the request body.
Backend POST api along with function that runs middleware:
case 'POST':
if (req.body instanceof FormData) {
await runMiddleware(req, res, upload.single('image'))
}
console.log('ID: ',req.query.id)
Courses.findByIdAndUpdate(req.query.id, req.body, {new: true}, (err, result) => {
if(err)
{
console.log('Error in findByIdAndUpdate: ',err)
res.status(400).json({ success: false, data: result })
}
else {
console.log('Success in findByIdAndUpdate: ',result)
res.status(200).json({ success: true, data: result })
}
})
below is the function
function runMiddleware(req, res, fn) {
return new Promise((resolve, reject) => {
fn(req, res, (result) => {
if (result instanceof Error) {
return reject(result)
}
return resolve(result)
})
})
}
Upload Middleware
import multer from "multer";
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, "public/uploads");
},
filename: (req, file, cb) => {
cb(null, "upload" + Date.now() + "-" + file.originalname)
}
})
module.exports = multer({storage})
Front-End API call
const createUpdateFormData = () => {
const data = {
title: getValues('title'),
categories: getValues('categories'),
description: getValues('description'),
image: (getValues('file') ? getValues('file')[0] : null),
}
let formData;
if (data.image) {
formData = new FormData();
Object.entries(data).forEach(([key, value]) => {
if(value)
formData.append(key, value);
});
}else {
formData = {}
Object.entries(data).forEach(([key, value]) => {
if(value)
formData[key] = value;
});
}
return formData
}
const handleUpdateRequest = (id,formData) => {
console.log(formData)
const updateReq = axios.post(`/api/courses/${id}`, formData)
toast.promise(updateReq, {
loading: "Processing...",
error: (err) => {
console.log(err)
if (err.response.status === 409)
return 'Course already exists!'
else
return 'Oops something went wrong!'
},
success: (res) => {
console.log(res)
const newState = courseState.map(course => course._id === id ? res.data.data : course)
setCourses(newState)
// console.log('NewState: ', courseState)
return "Course updated successfully!"
}
});
}
I am using the useForm hook

React Native && Node js How to upload image

I am having trouble uploading an image from my react native app. I have a react app that uploads images to the backend from camera as a file.
let pic = await camera.current.takePictureAsync({
quality: 1,
base64: true,
});
setPicture(pic);
Then
onPress={() => {
const formData = new FormData();
formData.append("file", {
name: picture + "",
type: picture.type,
uri:
Platform.OS === "ios"
? picture.uri.replace("file://", "")
: picture.uri,
});
console.log(formData);
httpClient
.post("demo/testsaveimg", formData)
.then((request) => {
if (request.data == "ok") {
console.log(request.data);
}
});
}}
This is my Formdata to service
and then, here is my service
app.post('/testsaveimg', async function (req, res, next) {
let storageUploadFile = multer.diskStorage({
destination: (req, file, next) => {
const folder = './test/'
if (!fs.existsSync(folder)) {
fs.mkdirSync(folder)
}
next(null, folder)
},
filename: (req, file, next) => {
const ext = file.mimetype.slice("/")[1]
next(null, `${file.fieldname}-${Date.now()}.${ext}`)
}
})
let UploadFile = multer({ storage: storageUploadFile }).single("files");
UploadFile(req, res, async function (err) {
console.log(req.file);
if (err instanceof multer.MulterError) {
return res.status(500).json(err);
} else if (err) {
console.log(99);
return res.status(500).json(err);
}
if (req.file != undefined) {
console.log("ok");
res.json("ok")
} else {
console.log("no");
res.json("no")
}
})
})
But there are no pictures in the folder "./test/" and response is "no"
that means "req.file = undefined"
What steps am I doing wrong?
or is there another way to write?

Sending webm blob to nodejs and saving it on the server

I'm having troubles saving an incoming webm blob to the server. I'm using react-video-recorder on NextJS like this:
<VideoRecorder
onRecordingComplete={(videoBlob) => {
// Do something with the video...
fetch("/api/video",
method: "post",
body: videoBlob,
})
.then(function (response) {
console.log("done");
return response;
})
.catch(function (err) {
console.log('error', err);
});
console.log(url);
// output: blob:http://localhost:3000/99a5b711-f3d5-481d-9e04-8981d1be3727
console.log(videoBlob);
// output BlobĀ {size: 307028, type: "video/webm;codecs="vp8,opus""}
}}
/>
On the api side I'm trying to save the file like this. It does save something, but is only the first chunk or buffer. How can I capture and write the file to my server?
export default async (req, res) => {
fs.writeFile('test.webm', req.body, function (err) {
if (err) return console.log(err);
console.log('video saved');
} );
}
I did that task by doing this.
I saved the recordingChunks/Video blob to a state and then sent it to the Nodejs server from Reactjs Frontend
FrontEnd code:-
const blob = new Blob(context.data.recordedChunks, {
type: "video/webm",
});
const fd = new FormData()
fd.append('video', blob)
axios.post(`${process.env.REACT_APP_BASE_URL}/video/blob_video`, fd)
.then((res) => console.log(res.data))
.catch((err) => console.log(err))
Backend code:-
router.post('/blob_video', async (req, res) => {
try {
if (req.files.video !== undefined) {
const video = req.files.video // this is your file do what ever you want with it
const videoname = Date.now() + req.files.video.name + ".webm"
video.mv(`${__dirname}/../your_path/${videoname}`, err => {
if (err) {
console.log(err)
return res.json({ err })
}
})
}
res.json(req.body)
} catch (err) {
res.json({ success: false, err: err, msg: "Server error" })
console.log(err)
}
})
Using express-fileupload to upload a file you can do it with your favourite one.

Node js file upload issue

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.

Download file from server (Nodejs Express > React)

how can i send a file(docx) to a user ?
this is my server code :
app.get('/api/topic/file/:id', function (req, res, next) {
Topic.findByIdAndUpdate(req.params.id)
.exec()
.then((topic) => {
let filepath = topic.news_file[0]
console.log('filepath', filepath)
res.download(filepath, topic.name + '.docx', function (err) {
if (err) {
console.log('api get file err ', err);
} else {
// decrement a download credit, etc.
}
});
}).catch((err) => console.log('error', err));
})
this does not trigger a download on the browser.
i am using react as front-end.
on the client i have a button triggering this upon click :
handleDownload() {
if (this.state.lastClicked) {
fetch("/api/topic/file/" + this.state.lastClicked._id)
.then(results => {
console.log('results', results)
return results;
})
} else {
//somthings...
}
}
Found a solution using downloadjs..
var download = require("downloadjs")
async handleDownload() {
const res = await fetch("/api/topic/file/" + this.state.lastClicked._id);
const blob = res.blob();
download(blob, this.state.lastClicked.name + '.docx');
}

Resources