I have a quick question. I would like to extract the file name of a wav file I am passing to my backend through axios using formData. I am not sure how to do this is nodejs. I would appreciate any help
Frontend:
//file is a Blob
var new_file = new File([file], bucket_string);
var formData = new FormData();
formData.append("wavfile", new_file, bucket_string);
const config = {
headers: { 'content-type': 'multipart/form-data' }
}
return await axios.post(`/files/upload-file`, formData, config);
//return await axios.post(`http://localhost:2000/files/upload-file`, data);
backend:
controller.js
async function uploadFile(req, res, next) {
fileService.uploadFile().then(function(val) {
res.json(val)
});
}
service.js
function uploadFile({ data }) {
const file = data;
var file_name = ?
//i would like to get the file name here
}
const express = require('express');
const multer = require('multer');
const app = express();
const upload = multer();
function uploadFile(req, res, next) {
console.log(req.file.originalname);
res.json({ok: true}).end();
}
app.post('/', upload.single('wavfile'), uploadFile);
app.listen(3001);
Related
I'm trying to send a file (.obj file) via formdata to my node server, it appears that everything is fine until the controller of the endpoint on the server throws an error that seems to be like the formdata parser is receiving an empty formdata object, here is the error in question. Now, here's my code:
Fron-end (where the request is being executed):
const data = new FormData();
data.append('file', this.props.filesSubmit, this.props.filesSubmit.name);
for (var pair of data.entries()) {
console.log(pair[0] + ', ' + pair[1]);
}
await axios
.post(
'https://hushpuppys-3d-hub-api.herokuapp.com/api/v1/modelfiles/',
data,
{
headers: {
'Content-Type': undefined,
},
}
)
.then((res) => {
console.log('File Upload Successful! Res: ', res);
})
.catch((err) => {
console.log(err);
});
Back-end endpoint Controller (Where request is received):
const AWS = require('aws-sdk');
const fs = require('fs');
const fileType = require('file-type');
const bluebird = require('bluebird');
const multiparty = require('multiparty');
// Keys Configuration to Access AWS
AWS.config.update({
accessKeyId: '[I erased this]',
secretAccessKey: '[I erased this]',
});
// Configuring AWS to work with promises
AWS.config.setPromisesDependency(bluebird);
// Creating S3 instance
const s3 = new AWS.S3();
// abstracts function to upload a file returning a promise
const uploadFile = (buffer, name, type) => {
const params = {
ACL: 'public-read',
Body: buffer,
Bucket: '[I erased this]',
ContentType: type.mime,
Key: `${name}.${type.ext}`,
};
return s3.upload(params).promise();
};
exports.fileUploaderController = (req, res) => {
const form = new multiparty.Form();
form.parse(req.body, async (error, fields, files) => {
if (error) throw new Error(error);
try {
const path = files.file[0].path;
const buffer = fs.readFileSync(path);
const type = fileType(buffer);
const timestamp = Date.now().toString();
const fileName = `bucketFolder/${timestamp}-lg`;
const data = await uploadFile(buffer, fileName, type);
return res.status(200).send(data);
} catch (error) {
return res.status(400).send(error);
}
});
};
I want to also add the code of my app.js where other middlewares manipulate the body, maybe that's also relevant to solve the problem:
const express = require('express');
const modelRouter = require('./routes/modelRoutes');
const modelFilesRouter = require('./routes/modelFilesRoutes');
const cors = require('cors');
const app = express();
// MIDDLEWARES
app.use(cors());
app.use(express.json({ limit: '50mb' }));
app.use(express.urlencoded({ limit: '50mb' }));
// ROUTES
app.use('/api/v1/models', modelRouter);
app.use('/api/v1/modelfiles', modelFilesRouter);
module.exports = app;
Ok, I got this problem solved a few minutes ago. I was basically passing a wrong parameter in the form.parse() method in the fileUploaderController controller from the Controller file, the method form.parse() needs the whole req variable to be passed as a parameter, not the body of the request (req.body) as I did in the code I posted with the question.
I'm trying to make a file upload API using multer gridFS, I used the documentation but I'm missing something:
this is my code:
const config = require("config");
const express = require("express");
const router = express.Router();
const dbURI = config.get("mongoURI");
const multer = require("multer");
const crypto = require("crypto");
const path = require("path");
const GridFsStorage = require("multer-gridfs-storage");
var storage = new GridFsStorage({
url: dbURI,
file: (req, file) => {
return new Promise((resolve, reject) => {
crypto.randomBytes(16, (err, buf) => {
if (err) {
return reject(err);
}
const filename = buf.toString("hex") + path.extname(file.originalname);
const fileInfo = {
filename: filename,
bucketName: "uploads"
};
resolve(fileInfo);
});
});
}
});
const upload = multer({ storage });
router.post("/upload", upload.single("file"), (req, res) => {
res.json({ msg: "file uploaded successfully" });
});
I get an error TypeError: Router.use() requires a middleware function but got a Object which basically tells me that upload.single is not a function, what is my error?
I found the mistake, I was missing module.exports = router;
i want to read the csv data uploaded to backened.
for this i am sending the data via post from front end..
frontend code:
fileEvent(e) {
this.filedata = e.target.files;
if (this.filedata.length > 0) {
const file: File = this.filedata[0];
console.log(file);
const formData: FormData = new FormData();
formData.append('files', file, file.name);
this.http.post('myUrl', {file: formData}, this.options)
.subscribe((res) => {
});
}
}
screenshot of my file:
now on backened i have written route on api.js that directs me
to the controller i have created.
my api.js code:
router.post('/product/csvdata', function (req, res) {
productimport.importcsvProduct(req, res);
});
and finally on my controller i am consoling my data:
var product = {
importcsvProduct: function (req,res) {
console.log(req.body.file);
}
};
module.exports = product;
but i am getting empty {} in console..??
can anyone check whats wrong with this..??
You need to use a file handling middleware in this case, such as multer.
const express = require('express')
const multer = require('multer')
const upload = multer({ dest: 'uploads/' })
const app = express()
app.post('/profile', upload.single('csvdata'), function (req, res, next) {
// req.file is the `csvdata` file
// req.body will hold the text fields, if there were any
})
So on first server I have route like this:
const express = require('express');
const router = express.Router();
const FormData = require('form-data');
const fetch = require('node-fetch');
const multer = require('multer');
const storage = multer.memoryStorage();
const upload = multer({ storage });
router.post('/', upload.single('file'), async (req, res) => {
const form = new FormData();
form.append('folderId', req.body.folderId);
form.append('file', req.file.buffer, req.file.filename);
const result = await fetch('http://localhost:3003/users', { method: 'POST', body: form }).then(res => res.json());
res.json(result);
})
On this server, it works fine, I can see req.file and it's buffer. So I wanna send this file (without storing it on first server, it exists only in memory and as buffer) to another.
Other server route is like this:
const express = require('express');
const router = express.Router();
const multer = require('multer');
const path = require('path');
const putanja = path.join(__dirname, '../uploads/users');
const storage = multer.diskStorage({
destination: (req, file, cb) => {
console.log('entered here?')
if (!req.body.folderId) return cb({ message: 'no folderId' });
if (!fs.existsSync(putanja + '/' + folderId)) fs.mkdirSync(putanja + '/' + folderId);
cb(null, putanja + '/' + folderId);
},
filename: (req, file, cb) => cb(null, file.originalname)
});
const upload = multer({ storage });
const fs = require('fs');
router.post('/', upload.single('file'), async (req, res) => {
console.log(req.body)
console.log(req.file)
res.json({ status: 'ok' })
})
So on second server, it doesn't even enter the multer middleware, req.file is always defined, and that console.log('entered here?') is never seen. Looks like I'm not passing data as multipart-form?
Also, second server, when sending file directly to it via postman, works.
So my question, how do I send that file? As a buffer? Stream? Base64? I think I tried everything, even changed node-fetch to request, but still no luck.
So on second server, it doesn't even enter the multer middleware, req.file is always defined, and that console.log('entered here?') is never seen. Looks like I'm not passing data as multipart-form?
So this mean your second server doesn't understand the Content-Type of request.
So do one thing add Content-Type parameter in header when you are sending request to second server
Add Content-Type to multipart/form-data
or if you don't know pass headers : {
'Content-Type' : undefined
} http will set header for you
You send your request to /users (http://localhost:3003/users) yet your second server expects the request on /.
Try changing either one to match the other.
'use strict';
const express = require('express');
const multer= require('multer');
const concat = require('concat-stream');
const request = require('request');
const router = express.Router();
function HttpRelay (opts) {}
HttpRelay.prototype._handleFile = function _handleFile (req, file, cb) {
console.log('hell0 proto');
file.stream.pipe(concat({ encoding: 'buffer' }, function (data) {
const r = request.post('/Endpoint you want to upload file', function (err, resp, body) {
if (err) return cb(err);
req.relayresponse=body;
cb(null, {});
});
const form = r.form();
form.append('uploaded_file', data, {
filename: file.originalname,
contentType: file.mimetype
});
}))
};
HttpRelay.prototype._removeFile = function _removeFile (req, file, cb) {
console.log('hello');
cb(null);
};
const relayUpload = multer({ storage: new HttpRelay() }).any();
router.post('/uploadMsgFile', function(req, res) {
relayUpload(req, res, function(err) {
res.send(req.relayresponse);
});
});
module.exports = router;
I have an API that is trying to make an HTTP request to an API that streams and image back to the me, then either stream that image back to the client making the request to me or wait until the image has been streamed to me and send it all at once.
I am using Express and request-promise.
Here's a shortened version of my code.
const express = require('express');
const router = express.Router();
const request = require('request-promise');
const imgFunc = async () => {
try {
const response = await request.get({
method: 'GET',
uri: `http://localhost:8080`,
});
return response;
} catch(err) {
console.log(err);
}
};
router.get('/', async function(req, res, next) {
try {
const response = await imgFunc();
return res.send(response);
} catch (err) {
console.log(err);
}
});
module.exports = router;
The image that I get back is just what I assume is the binary data and I don't know if I need to do something at the request-promise level to make that right or when I send it back to the client.
The server that I have running at localhost:8080 mimics the actual server that I will be hitting when this is all said and done.
You could pipe the streams directly rather than using request-promise.
const express = require('express');
const router = express.Router();
const https = require('https');
router.get('/', function(req, res) {
const url = 'https://www.gravatar.com/avatar/2ea70f0c2a432ffbb9e5875039645b39?s=32&d=identicon&r=PG&f=1';
const request = https.get(url, function(response) {
const contentType = response.headers['content-type'];
console.log(contentType);
res.setHeader('Content-Type', contentType);
response.pipe(res);
});
request.on('error', function(e){
console.error(e);
});
});
module.exports = router;
Or using the request library on which request-promise is based:
const express = require('express');
const router = express.Router();
const request = require('request');
router.get('/', function(req, res) {
const url = 'https://www.gravatar.com/avatar/2ea70f0c2a432ffbb9e5875039645b39?s=32&d=identicon&r=PG&f=1';
request.get(url).pipe(res);
});
module.exports = router;
you could pipe the streams directly through axios
const express = require('express');
const router = express.Router();
const axios = require("axios");
router.get('/', function(req, res) {
const link = 'https://app.idesk360.com/media/logos/iDeskLoginTxt.png';
const arrayBuffer = await axios.get(link, {responseType: 'stream'});
const contentType = arrayBuffer.headers["content-type"];
res.setHeader('content-type', contentType);
arrayBuffer.data.pipe(res);
});
module.exports = router;