I have been following this video in order to know how to use Multer to upload files.
I have then implemented an image-upload feature in one Node.js app of mine.
Now I would like to use Multer to upload the contents of a blob containing audio data. What is the way to go? I already tried a bit following what I learned, but I already have some issues:
I am now dealing with audio data instead of graphic data.
I do not have a field name any more to put as an argument for the multer({ storage: storage }).single(...); function call.
I hope someone with experience (using Multer) will provide some guidance on this.
For reference, here is my code for when the upload button is clicked:
uploadVceRcd.onclick = e => {
var reader = new FileReader();
reader.onload = function(event) {
var fd = {};
fd["fname"] = "VoiceRecord_"+Date.now()+".opus";
fd["data"] = event.target.result;
$.ajax({
type: 'POST',
url: 'VoiceUpLoad',
id: document.getElementById('sentID').innerText,
data: fd,
dataType: 'text'
}).done(function(data) {
console.log('uploadAudio - Done !');
console.log(data);
});
};
reader.readAsDataURL(blob);
}
And here is my code for handling the matching VoiceUpLoad route inside index.js:
app.post('/VoiceUpLoad', function (req, res) {
upload(req, res, function (err) {
if (err) {
if (err instanceof multer.MulterError) {
// A Multer error occurred when uploading.
console.log('A Multer error occurred when uploading. !!!');
} else {
// An unknown error occurred when uploading.
console.log('A unknown error occurred when uploading. !!!');
console.log(err);
}
} else {
// Everything looks fine.
console.log('All seems OOKK !!!');
console.log(req.file);
if (req.file == undefined) {
console.log('req.file == undefined!!!');
} else {
console.log('SHOULD BE OOKK !!!');
.......
}
}
});
});
When I run this code I get the following in the logs:
... app[web.1]: All seems OOKK !!!
... app[web.1]: undefined
... app[web.1]: req.file == undefined!!!
You may use following code to upload the audio file,
reader.onload = function(event) {
var formData = new FormData();
formData.append('fname', "VoiceRecord_"+ Date.now() + ".opus")
formData.append('data', event.target.result)
$.ajax({
type: 'POST',
url: 'some/path',
data: formData,
contentType: false,
cache: false,
processData: false,
}).done(function(data) {
console.log('uploadAudio - Done !');
console.log(data);
});
});
Please try this I will explain it if it works.
Related
I'm a bit lost on the way a video is being send from React Native to the backend and having it working on S3. All help would be appreciated especially where I might be going wrong.
Initially, from React Native I use the Expo Camera to record a video. Once it has stopped recording, we use fetch to send the data as follows:
const startRecording = async () => {
setIsRecording(true);
const video = await camera.recordAsync({
maxDuration: 15
});
const data = new FormData();
data.append('video', {
name: 'mobile-video-upload',
uri: video.uri
});
try {
const res = await fetch('url/users/testing', {
method: 'post',
body: data
});
} catch (error) {
console.log('error uploading');
}
};
the type of Data we get back from Camera component through IOS is:
Object {
"uri": "...Camera/D3B7B5F5-6A17-4C45-A0BE-897956A9E637.mov",
}
On the backend I'm using a middleware known as multer. My route for the backend looks like this
const multer = require('multer');
const upload = multer({ dest: 'uploads/' });
router.post('/testing', upload.single('video'), async (req, res) => {
let buffer = null;
fs.readFile(req.file.path, (err, data) => {
if (err) {
console.log('There was an error reading file: ', err);
}
buffer = data;
});
const params = {
Bucket: bucket_name,
Key: 'testing124.mov',
ContentType: req.file.mimetype,
Body: buffer
};
try {
let uploadPr = await s3.putObject(params).promise();
console.log(uploadPr);
} catch (error) {
console.log('There was an err ', error);
}
The data we see in req.file is:
{
fieldname: 'video',
originalname: 'mobile-video-upload',
encoding: '7bit',
mimetype: 'video/quicktime',
destination: 'uploads/',
filename: 'aed58f2dfbcc8daa7964fb3df7d3b4f4',
path: 'uploads/aed58f2dfbcc8daa7964fb3df7d3b4f4',
size: 480422
}
What might I be doing wrong in order to have a valid video uploaded? I'm unable to view the video from s3 whether I download the file or try using the link and viewing the video.
Thank you for all the help.
If your already using multer, use this:
https://www.npmjs.com/package/multer-s3
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.
Here is my code where I am getting the upload video and checking it extension when extention is not mp4 i want to return else statement and pass the the error from server but when i am getting this error and when i am console.log this error this print the server not responding 505 error it is working fine with when extention is mp4.
const videoStorage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, config.videoStorage);
},
filename: function (req, videoFile, cb) {
if (path.extension(videoFile.originalname) !== '.mp4') {
const name = `${videoFile
.fieldname}-${Date
.now()}_${
videoFile.originalname}`;
return cb(null, name.replace(/\s/g, ""));
} else {
return cb(new Error("sorry"));
}
}
});
MediaService
.uploadVideo(formData, this.getUploadProgress)
.then(data => {
let order = {
...this.state.project
};
if (!order.project) {
order = {
project: {
mediaId: data
}
};
}
order.project.mediaId = data;
console.log("videoid added ===", order);
this.setState({uploading: false, videoId: data, isValid: true, project: order});
message.success("Video uploaded successfully");
})
.catch(error => {
message.error(error);
this.setState({message: error, uploading: false});
});
};
Instead of throwing error,you can pass flag like this:
return cb({success:false,message:"false"});
This you can access in success promise of uploader.
Because when you are saying new Error(), i think it will throw an error on server side and it will not be able to send response to client.that is why you are not getting response on client side.
I am having a problem to redirect the page after a successful file upload using multer. With the file upload i am also saving some text into the database. Here's my code.
Question :
When the file and the contents are saved in the DB how can I redirect the page to a new URL ?
I am currently using res.redirect('product/item'); but nothing happens. I also tried using res.render, but the page did not redirect.
Multer method to upload a file to Amazon S3
var upload = multer({
storage: multerS3({
s3: s3,
bucket: 'nameofthebucket',
metadata: function (req, file, cb) {
var ext = file.originalname.split('.').pop();
cb(null, {fieldName: 'file.fieldname' + '.' + ext});
},
filename: function(req,file,cb){
var ext = file.originalname.split('.').pop();
cb(null, Date.now() + '.' + ext);
},
key: function (req, file, cb) {
var ext = file.originalname.split('.').pop();
cb(null, Date.now() + '.' + ext);
}
})
})
var upload = upload.array('fileup', 10);
The code responsible to upload the file and the content
router.post('/uploadfileandcontent',function(req,res,next){
upload(req,res,function(err) {
if(err) {
} else {
saveRecordsToDB(req, function(err,data){
if (err) {
res.redirect('/errorpage');
} else {
res. redirect('product/item');
}
});
}
});
});
Function that saves records to DB and makes the callback
function saveRecordsToDB (req, callback){
var args = {
data: {
"name" : req.body.name, //
"age" : req.body.age
},
headers: { "Content-Type": "application/json" }
};
// registering remote methods
client.registerMethod("postMethod", "http://url/uploadfileandcontent", "POST");
var req =client.methods.postMethod(args, function (data, response) {
callback(null, 'success?');
});
req.on('error', function (err) {
console.log('error');
});
}
Note: I also made use of NODE REST CLIENT to send http request.
This should work. Tell me if it doesn't.
router.post('/uploadfileandcontent', function(req,res,next){
upload(req,res,function(err) {
if(err) {
res.send('Error while uploading.');
}
saveRecordsToDB(req, function(err,data){
if (err) {
console.log(err);
req.flash('error', { msg: 'Error while saving data.' }); // Flash message -> need to configure your template to show it
}
// Saved to DB
req.flash('success', { msg: 'Saved' });
res.redirect('/product/item'); // go to this page
});
});
});
UPDATE
You will need to include const flash = require('express-flash'); to use flash message. Then you can load it to your app like this: app.use(flash());. The app is express loaded like this: const app = express();.
In your HTML you will access it in an array. Example using Jade:
//success
if messages.success
for success in messages.success
div #{success.msg} // Saved
//Error
if messages.errors
for error in messages.errors
div #{error.msg} // Error while saving data.
I am very new to express and node. I was trying to upload an image using multiparty and code given here.
I have put a check for file size. When I upload a file of size greater than the limit it lands in the "problem section". The problem is the server hangs and responds back only after request timeout. I have tried many solution on stack overflow but nothing seems to work. It works if the file size is below the limit. I am very sure that the code reaches the problem section and there is no problem with the upload logic. But it seems that I have to do something in the "problem section". Please tell me what am I missing.
I have replaced the code in the problem section with
next(), res.send(), res.end(), next(err), return; but It does not work. It hangs no matter what.
Following is the code:
router.post("/image", function(req, res, next) {
if(req.user) {
upload.uploadToS3(req, S3_BUCKET, S3_PROFILE_IMAGE_FOLDER, function(result) {
if(result.error != null && result.error === false) {
models.Customer.update({
orignalImage : result.fileLocation
},{
where : { mobileNumber : req.user.mobileNumber}
}).then(function(customer) {
if(customer) {
res.send({
url: result.fileLocation,
error : false
});
} else {
res.status(400);
res.send({error : true,
error_message : 'Image upload failed'});
}
});
} else {
//PROBLEM SECTION
res.status(404);
res.json({error : true, error_message : result.error_message});
}
});
} else {
res.status(403);
res.send({message: "access denied"});
}
});
response after timeout
Please tell me if you need more details I will upload it.
var uploadToS3 = function(req, S3_BUCKET, folder, callback) {
var s3Client = knox.createClient({
secure: false,
key: awsConfig.accessKeyId,
secret: awsConfig.secretAccessKey,
bucket: S3_BUCKET,
});
var headers = {
'x-amz-acl': 'public-read',
};
var form = new multiparty.Form();
var batch = new Batch();
batch.push(function(cb) {
form.on('part', function(part) {
var validity = validateFile({type : part.headers['content-type'], name : part.filename, length : part.byteCount});
console.log(validity);
if(validity.isValid) {
cb(null, { filename : folder+"/"+generateFileName({name : part.filename}), part : part});
} else {
cb({error : true, error_message : validity.reason, part:part }, "advra kedavra");
}
});
});
batch.end(function(err, results) {
if (err) {
console.log(err);
err.statusCode = 200;
callback(err);
} else {
form.removeListener('close', onEnd);
var result = results[0];
var part = result.part;
var destPath = result.filename;
var counter = new ByteCounter();
part.pipe(counter); // need this until knox upgrades to streams2
headers['Content-Length'] = part.byteCount;
s3Client.putStream(part, destPath, headers, function(err, s3Response) {
result = {};
if(err) {
console.log(err);
result.error = true;
result.error_message = "Problem in uploading!";
} else {
console.log(s3Response.req.url);
result = {error: false, statusCode : s3Response.statusCode, message : "file upload successful.", fileLocation : s3Response.req.url};
}
callback(result);
});
part.on('end', function() {
console.log("File upload complete", counter.bytes);
});
}
});
function onEnd() {
console.log("no uploaded file");
callback({error:false, error_message:"no uploaded file."});
}
form.on('error', function(err) {
console.log('Error parsing form: ' + err.stack);
});
form.on('close', onEnd);
form.parse(req);
}
After a 3 day long search for the answer I found one answer. Express.js close response
The problem section should be the following :
res.status(400);
res.set("Connection", "close");
res.json({error:true, error_message : "<some - error message>"});
You should simply add a .end() after setting the status as: res.status(400).end();
See official docs
res.end([data] [, encoding])
Ends the response process. This method actually comes from Node core, specifically the response.end() method of http.ServerResponse.
Use to quickly end the response without any data. If you need to respond with data, instead use methods such as res.send() and res.json().
res.end();
res.status(404).end();
res.status(400);
res.set("Connection", "close");
res.json({error:true, error_message : "<some - error message>"});
I am not sure that solves your issue. The 'problem section' is in your callback, which would only run after the upLoadToS3 function runs. The 'problem' is probably with that function. You might have to refactor that to handle large file uploads.