I am trying to upload a file to S3 on Amazon by creating an API,,, however, I am having issues while uploading the file.
The API has an issue when I select the file using postman I get the error below
I don't get the source of the issue
MulterError: Unexpected field
at wrappedFileFilter (E:\MyProjects\reapmgtapi\node_modules\multer\index.js:40:19)
at Busboy.<anonymous> (E:\MyProjects\reapmgtapi\node_modules\multer\lib\make-middleware.js:114:7)
at Busboy.emit (events.js:198:13)
at Busboy.EventEmitter.emit (domain.js:448:20)
at Busboy.emit (E:\MyProjects\reapmgtapi\node_modules\busboy\lib\main.js:38:33)
at PartStream.<anonymous> (E:\MyProjects\reapmgtapi\node_modules\busboy\lib\types\multipart.js:213:13)
at PartStream.emit (events.js:198:13)
at PartStream.EventEmitter.emit (domain.js:448:20)
at HeaderParser.<anonymous> (E:\MyProjects\reapmgtapi\node_modules\dicer\lib\Dicer.js:51:16)
at HeaderParser.emit (events.js:198:13)
Here are my project files
multer.config.js
const multer = require('multer');
var storage = multer.memoryStorage()
var upload = multer({ storage: storage });
module.exports = upload;
controller.js
const s3 = require('../config/s3.config');
const env = require('../config/s3.env');
exports.doUpload = (req, res) => {
const params = {
Bucket: env.Bucket,
Key: req.file.originalname,
Body: req.file.buffer
}
s3.upload(params, (err, data) => {
if (err) {
res.status(500).send("Error is as follows -> " + err);
}
res.send("File uploaded successfully! -> keyname = " + req.file.originalname);
});
}
s3.router.js
let express = require('express');
let router = express.Router();
let upload = require('../config/multer.config');
const awsWorker = require('../controllers/controller');
router.post('/api/files/upload', upload.single("file"), awsWorker.doUpload);
module.exports = router;
the code is fine,,, I just had to create a request with a file with "file" as the key and the file input as the parameter... I was trying to input the originalname and buffer parameters which should be extracted from the file
Related
I am using express + multer-S3 to upload files to AWS S3. Using the following code, I get an internal server error 500 and I don't understand what I am doing wrong.
const aws = require("aws-sdk");
console.log("Require AWS");
const multer = require("multer");
const multerS3 = require("multer-s3");
const s3 = new aws.S3();
aws.config.update({
secretAccessKey: process.env.S3_ACCESS_SECRET,
accessKeyId: process.env.S3_ACCESS_KEY,
region: "eu-west-3",
});
const fileFilter = (req, file, cb) => {
if (file.mimetype === "image/jpeg" || file.mimetype === "image/png") {
cb(null, true);
} else {
cb(new Error("Invalid file type, only JPEG and PNG is allowed!"), false);
}
};
const upload = multer({
fileFilter,
storage: multerS3({
acl: "public-read",
s3: s3,
bucket: "schubox",
contentType: multerS3.AUTO_CONTENT_TYPE,
metadata: function (req, file, cb) {
console.log("Called when saving image to AWS");
cb(null, { fieldName: "TESTING_METADATA" });
},
key: function (req, file, cb) {
console.log("FILE ==> " + JSON.stringify(file));
cb(null, Date.now().toString());
},
}),
});
And in my route
router
.route("/rayons")
.get(auth, ctrlRayons.rayonsListe)
.post(auth, **upload.single("fichier")**, ctrlRayons.rayonsCreerUn);
I get this error
Missing credentials in config, if using AWS_CONFIG_FILE, set AWS_SDK_LOAD_CONFIG=1"
Error: connect EHOSTDOWN 169.254.169.254:80 - Local (192.168.1.10:56879) at internalConnect (net.js:934:16) at defaultTriggerAsyncIdScope (internal/async_hooks.js:452:18) at net.js:1022:9 at processTicksAndRejections (internal/process/task_queues.js:77:11)
What am I doing wrong?
My AWS S3 account is ok, I have my Id and my secret ok, but nothing is written in my bucket. All the tutorials show the same procedure as the one I use.
Thanks again for your help.
Can't upload files to the server. I've used npm install express-fileupload and also did the var fileUpload = require('express-fileupload') and app.use(fileUpload()). And while calling
router.post('/add-products',(req,res)=>{
console.log(req.body);
console.log(req.files.image);
It says cannot read image of null.
I can give you a working full example.
Project structure:
- storage (empty folder)
- routes
-> upload.route.js
- controllers
-> upload.controller.js
index.js
index.js
const express = require('express');
const app = express();
const route = require('./routes/upload.route');
app.use('/', route);
let port = 8000;
app.listen(port);
console.log(`API listens localhost:${port}`);
This is your upload.route.js
const express = require('express');
const router = express.Router();
const { uploadController } = require('../controllers/upload.controller');
router.use('/media/upload', uploadController);
module.exports = router;
This is upload.controller.js
const formidable = require('formidable');
const path = require('path');
exports.upload = async (req, res) => {
try {
// Receive the media and store it
let [uploadPath, filename] = await processUpload(req);
return res
.status(200)
.send({
success: 1,
message: "File uploaded",
filename,
uploadPath
});
} catch (error) {
return res
.status(400)
.send({
success: 0,
message: "Ops! Something went wrong",
errorObject: error.message
});
}
}
function processUpload(req) {
return new Promise((resolve, reject) => {
try {
let uploadDir = __dirname + `/../storage`;
// We used helper formidable package
let form = new formidable.IncomingForm()
form.multiples = true;
form.keepExtensions = true;
// Upload path
form.uploadDir = uploadDir;
let result;
form.on('fileBegin', function (name, file) {
if (!file.type) reject(new Error("No media specified!"));
const fileExt = path.extname(file.name);
let filename = "test" + fileExt;
file.path = path.join(uploadDir, filename);
// Return the path where file uploaded
result = [file.path, uuid];
});
form.parse(req, (err, fields, files) => {
if (err) return reject("Upload failed.");
resolve(result);
});
} catch (error) {
reject("Upload failed.");
}
});
}
When you call localhost:8000/media/upload with a POST or PUT request with postman form-data. You can see the uploaded file under the storage folder in the project.
Let me know if something goes wrong with the code
Note: You need to use formidable (For uploading) package to run the example
i want uplaod tow file in one request in nodejs and i using the moulter for this work .
this is my request in postman :
and i using the multer in routing :
router.post(
"/Create",
UploadProfileHandler.single("signerProfile"),
UploadPosterHandler.single("signerPoster"),
SignerValidation.CreateHandle(),
SignerController.CreateSigner
);
and this isnto the multer :
signer Profile Multer :
const multer = require("multer");
const fs = require("fs");
const mkdirp = require("mkdirp");
const path = require("path");
const GetDirectory = () => {
let year = new Date().getFullYear();
let month = new Date().getMonth();
let day = new Date().getDay();
return `src/public/uploads/signer/profile/${year}/${month}/${day}`;
};
const SignerStorage = multer.diskStorage({
destination: (req, file, cb) => {
console.log(file,req.body)
let dir = GetDirectory();
mkdirp(dir).then((made) => {
cb(null, dir);
});
},
filename: (req, file, cb) => {
let fileName = GetDirectory() + "/" + file.originalname;
cb(null, file.originalname);
},
});
const UploadSigner = multer({
storage: SignerStorage,
});
module.exports = UploadSigner;
and this is singer Poster Multer :
const multer = require("multer");
const fs = require("fs");
const mkdirp = require("mkdirp");
const path = require("path");
const GetDirectory = () => {
let year = new Date().getFullYear();
let month = new Date().getMonth();
let day = new Date().getDay();
return `src/public/uploads/signer/poster/${year}/${month}/${day}`;
};
const SignerStorage = multer.diskStorage({
destination: (req, file, cb) => {
let dir = GetDirectory();
mkdirp(dir).then((made) => {
cb(null, dir);
});
},
filename: (req, file, cb) => {
let fileName = GetDirectory() + "/" + file.originalname;
cb(null, file.originalname);
},
});
const UploadSigner = multer({
storage: SignerStorage,
});
module.exports = UploadSigner;
But when I want to upload both files at the same time it show me this error :
MulterError: Unexpected field
at wrappedFileFilter (F:\Projects\Nodejs\SalesSignal\node_modules\multer\index.js:40:19)
at Busboy. (F:\Projects\Nodejs\SalesSignal\node_modules\multer\lib\make-middleware.js:114:7)
at Busboy.emit (events.js:315:20)
at Busboy.emit (F:\Projects\Nodejs\SalesSignal\node_modules\busboy\lib\main.js:38:33)
at PartStream. (F:\Projects\Nodejs\SalesSignal\node_modules\busboy\lib\types\multipart.js:213:13)
at PartStream.emit (events.js:315:20)
at HeaderParser. (F:\Projects\Nodejs\SalesSignal\node_modules\dicer\lib\Dicer.js:51:16)
at HeaderParser.emit (events.js:315:20)
at SBMH.emit (events.js:315:20)
at SBMH._sbmh_feed (F:\Projects\Nodejs\SalesSignal\node_modules\streamsearch\lib\sbmh.js:159:14)
at SBMH.push (F:\Projects\Nodejs\SalesSignal\node_modules\streamsearch\lib\sbmh.js:56:14)
at HeaderParser.push (F:\Projects\Nodejs\SalesSignal\node_modules\dicer\lib\HeaderParser.js:46:19)
at Dicer._oninfo (F:\Projects\Nodejs\SalesSignal\node_modules\dicer\lib\Dicer.js:197:25)
at SBMH. (F:\Projects\Nodejs\SalesSignal\node_modules\dicer\lib\Dicer.js:127:10)
whats the problem ? how can i solve this problem ???
To handle multiple fields you cannot call the .single() middleware multiple times, instead you should use .array() or .fields(). Here's an example how you would use the latter:
app.post("/upload", upload.fields([
{name: 'signerPoster'},
{name: 'signerProfile'}
]), (req, res) => {
// do something with req.files and req.body
});
The uploaded files will be populated under req.files.signerPoster and req.files.signerProfile and req.body will contain the text-based fields.
I'm sending the image using formdata in angular to my nodejs api. and in nodejs i'm storing that file at myfolder but when i open my stored image file its shows
"Abc.jpeg It appears that we don't support this file format"
From nodejs i used multiparty, then i used formidable but getting same error in both
I compared the size of file before uploading (original file) size was 78kb but after uploading the file size become 111kb.
Nodejs Code
var form = new formidable.IncomingForm();
form.parse(req, function (err, fields, files) {
console.log(files.fileDetails.path);
var oldpath = files.fileDetails.path;
var newpath = 'C:/storage/myfolder/' + files.fileDetails.name;
fs.rename(oldpath, newpath, function (err) {
if (err) throw err;
res.write('File uploaded and moved!');
res.end();
});
})
Angular Code
public OnSubmit(formValue: any) {
let main_form: FormData = new FormData();
for(let j=0;j<this.totalfiles.length; j++) {
console.log("the values is ",<File>this.totalfiles[j]);
console.log("the name is ",this.totalFileName[j]);
main_form.append(fileDetails,this.totalfiles[j])
}
console.log(formValue.items)
this._SocietyService.postFiles(main_form).subscribe(data => {
console.log("result is ", data)
})
}
var path = require('path')
var multer = require('multer')
var storage = multer.diskStorage({
destination: 'C:/storage/myfolder/',
filename: function (req, file, cb) {
cb(null, file.fieldname + '-' + Date.now());
}
})
var upload = multer({ storage: storage })
You can use the multer its a vary handy middleware to handle form/multipart data.
I'm attempting to handle file uploads using a Google Cloud Function. This function uses Busboy to parse the multipart form data and then upload to Google Cloud Storage.
I keep receiving the same error: ERROR: { Error: ENOENT: no such file or directory, open '/tmp/xxx.png' error when triggering the function.
The error seems to occur within the finish callback function when storage.bucket.upload(file) attempts to open the file path /tmp/xxx.png.
Note that I can't generate a signed upload URL as suggested in this question since the application invoking this is an external, non-user application. I also can't upload directly to GCS since I'll be needing to make custom filenames based on some request metadata. Should I just be using Google App Engine instead?
Function code:
const path = require('path');
const os = require('os');
const fs = require('fs');
const Busboy = require('busboy');
const Storage = require('#google-cloud/storage');
const _ = require('lodash');
const projectId = 'xxx';
const bucketName = 'xxx';
const storage = new Storage({
projectId: projectId,
});
exports.uploadFile = (req, res) => {
if (req.method === 'POST') {
const busboy = new Busboy({ headers: req.headers });
const uploads = []
const tmpdir = os.tmpdir();
busboy.on('file', (fieldname, file, filename, encoding, mimetype) => {
const filepath = path.join(tmpdir, filename)
var obj = {
path: filepath,
name: filename
}
uploads.push(obj);
var writeStream = fs.createWriteStream(obj.path);
file.pipe(writeStream);
});
busboy.on('finish', () => {
_.forEach(uploads, function(file) {
storage
.bucket(bucketName)
.upload(file.path, {name: file.name})
.then(() => {
console.log(`${file.name} uploaded to ${bucketName}.`);
})
.catch(err => {
console.error('ERROR:', err);
});
fs.unlinkSync(file.path);
})
res.end()
});
busboy.end(req.rawBody);
} else {
res.status(405).end();
}
}
I eventually gave up on using Busboy. The latest versions of Google Cloud Functions support both Python and Node 8. In node 8, I just put everything into async/await functions and it works fine.