I have deployed the express app on vercel, other api are working fine but uploading image one is giving the error "Internal Server Error"
upload api in index.js
app.post("/api/upload", upload.single("file"), async (req, res) => {
res.status(200).json("File has been uploaded");
});
multer configuration
const multerStorage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, "./images");
},
filename: (req, file, cb) => {
cb(null, req.body.name);
},
});
const upload = multer({ storage: multerStorage });
I am trying in postman by entering the form data which includes name and file but if I try with only uploading file in binary, it is getting successful.
Path is fine, api is working smoothly in local but dont know why it is not working after deploying.
Github repo - https://github.com/JavaKaran/techducant-backend
Edit - 1
Error (getting in postman)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Error</title>
</head>
<body>
<pre>Internal Server Error</pre>
</body>
</html>
Edit - 2
vercel error for upload api
[POST] /api/upload
2022-12-14T15:52:55.912Z 0988f1fa-ba5c-49b8-ae08-889cc67e7889 ERROR Error: EROFS: read-only file system, open 'images/virtual.jpg'
Related
I was creating a Node App using Express JS. There's a route which accepts a POST Request. The app works fine on localhost, but when I host on Cpanel Shared Hosting, I get the following error for POST request. GET works fine. Can anyone please help or guide where I went wrong?
<html lang="en">
<head>
<meta charset="utf-8">
<title>Error</title>
</head>
<body>
<pre>Cannot GET /v1/email</pre>
</body>
</html>
My Express JS code
var app = express();
var em =require('./mailjet')
var bodyParser = require('body-parser');
app.use(bodyParser.json())
app.get('/v1', function (req, res) {
return res.json('Hello World');
})
app.post('/v1/email', function (req, res) {
let {name, email, message}=req.body
if (!name || !email || !message){
return res.status(400).send({
'Message':'Bad Request'
})
}
em.request(name, email, message)
return res.status(200).send({
'Message':'Email Sent'
});
})
app.listen()
I am getting an error status code 404 while calling a function locally in nodejs server through firebase serve command.
My schedule.js file
const scheduleOfScheduledQuiz = async (req, res) => {
try {
const data = await getScheduledData();
return res.status(200).json({
message: "Scheduled for today:- ",
data: data
})
} catch (error) {
console.log("erro", error);
return res.status(500).json({
message: "Something went wrong....!!!"
})
}
}
module.exports = {
scheduleOfScheduledQuiz
}
getScheduledData() is a function which gets some data from the firebase realtime database
My index.js file
const functions = require("firebase-functions");
const app = require("express")();
//path to scheduleOfScheduledQuiz() function file
const scheduleOfScheduledQuiz = require("./handlers/Quiz/Scheduled_Quiz/scheduler");
app.get("*/scheduled-quiz/schedule/", scheduleOfScheduledQuiz.scheduleOfScheduledQuiz);
exports.api = functions.runWith({
memory: '2GB',
timeoutSeconds: '60'
}).https.onRequest(app);
So the error what i am getting :-
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Error</title>
</head>
<body>
<pre>Cannot GET /predicta-6e51d/us-central1/api/scheduled-quiz/schedule/%0A</pre>
</body>
</html>
with status code 404
My package.json file
Global node js version - 12
firebase node js version - 10
"express": "^4.17.1",
"firebase": "^7.15.0",
"firebase-functions": "^3.7.0",
I am running this function locally on my nodejs server through firebase serve command.
NOTE:- when i am trying to run the same function on some other file it is perfectly running but not in this file.
Please Help
Thank You
I am implementing a file upload using Plupload in the frontend and express nodejs in the backend with multer middleware for multipart/form upload. There is currently no example available, so this is what I got so far:
HTML frontend:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Test</title>
</head>
<ul id="filelist"></ul>
<br />
<div id="container">
<a id="browse" href="javascript:;">[Browse...]</a>
<a id="start-upload" href="javascript:;">[Start Upload]</a>
<br />
<pre id="console"></pre>
</div>
<script src="/plupload/js/plupload.full.min.js"></script>
<script type="text/javascript">
var uploader = new plupload.Uploader({
browse_button: 'browse', // this can be an id of a DOM element or the DOM element itself
url: '/upload'
});
uploader.init();
uploader.bind('FilesAdded', function(up, files) {
var html = '';
plupload.each(files, function(file) {
html += '<li id="' + file.id + '">' + file.name + ' (' + plupload.formatSize(file.size) + ') <b></b></li>';
});
document.getElementById('filelist').innerHTML += html;
});
uploader.bind('UploadProgress', function(up, file) {
document.getElementById(file.id).getElementsByTagName('b')[0].innerHTML = '<span>' + file.percent + "%</span>";
});
uploader.bind('Error', function(up, err) {
document.getElementById('console').innerHTML += "\nError #" + err.code + ": " + err.message;
});
document.getElementById('start-upload').onclick = function() {
uploader.start();
};
</script>
</html>
It basically just the plupload quickstart guide: http://www.plupload.com/docs/v2/Getting-Started
Backend using node express. I trimmed my code down to a minimum working version for use here on SO:
const path = require('path');
const express = require('express');
var multer = require('multer');
var upload = multer({ dest: 'uploads/' });
// Create express
const app = express();
app.use(express.static('public'));
app.post('/upload', upload.array('file'), function(req, res){
console.log(req.files);
})
app.listen(3000, function () {
console.log('App running...');
});
Basically, just a regular express app with multer package and serving static files.
Question:
How do I upload files using Plupload in the front-end and NodeJS (using express, multer) in the backend? It should also support chunking.
You can use the fileFilter function to validate your files before they are getting uploaded, this function enables you to validate filenames, extensions and which files should be uploaded and which should be skipped.
For, eg, Let's assume that you want the user to upload only "PDF" files, you can write a filter like this,
multer({
fileFilter: function (req, file, cb) {
if (file.mimetype !== 'application/pdf') {
req.fileValidationError = 'Only PDF files can be uploaded';
return cb(null, false, new Error('Only PDF files can be uploaded'));
}
cb(null, true);
}
});
Just in case if you want to restrict the user to upload files within certain MB, you can make use of the limits property which can be set as,
limits: { fileSize: the_file_size_which_you_want_to_allow }
And finally if you want to have a common file naming pattern in your destination directory (where the files gets uploaded) you can make use of the fileName function like this, (in the below example we are appending a hyphen and timestamp to the filename).
filename: function (req, file, cb) {
cb(null, file.fieldname + '-' + Date.now())
}
UPDATE
You can make use of the plupload node module which will take care of the express-plupload communication which you're trying to sort out.
Hope this helps!
The concept is still not clear to me yet.
For a very basic case, i can upload a file (say myFile.txt) using multer, and keep its original name in the server side.
const upload = multer({ dest: `${UPLOAD_PATH}/` }); // multer configuration
Now another person happen to upload a different file with same file name myFile.txt to the same folder in server side. Will it overwrite the previous one ?
How do you normally manage this ? Thanks !
Will it overwrite the previous one ?
Yes it will definitely replace with the new one.Here is my code .In this code if you use a same file name from different locations or from the same location it won't replaces.It keeps both the files in destination.Server code server.js
var express=require('express');
var multer=require('multer');
var path = require('path')
var app=express();
var ejs = require('ejs')
app.set('view engine', 'ejs')
var storage = multer.diskStorage({
destination: function(req, file, callback) {
callback(null, './public/uploads')
},
filename: function(req, file, callback) {
callback(null, file.fieldname + '-' + Date.now() + path.extname(file.originalname))
//callback(null, file.originalname)
}
})
app.get('/api/file',function(req,res){
res.render('index');
});
app.post('/api/file', function(req, res) {
var upload = multer({
storage: storage}).single('userFile');
upload(req, res, function(err) {
console.log("File uploaded");
res.end('File is uploaded')
})
})
app.listen(3000,function(){
console.log("working on port 3000");
});
If you observe the code callback(null, file.originalname) this line will keep the original file name in destination and will replace the file when it gets the same name.If you don't want this then use callback(null, file.fieldname + '-' + Date.now() + path.extname(file.originalname)).This callback changes the name of file in destination.
Make a views folder and keep this file in it.ejs code from which you can choose a file to upload index.ejs
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<form id="uploadForm" enctype="multipart/form-data" method="post">
<input type="file" name="userFile" />
<input type="submit" value="Upload File" name="submit">
</form>
</body>
</html>
Run the code as node server.js.Open the browser and type http://localhost:3000/api/file.Choose a file to upload and see the destination folder.Hope this helps for you.
actually Multer saves the file in a given path (as specied by you) but with a different randomised filename. It will not override the file even if the name of the file is the same.
So your UPLOAD_PATH will have multiple files even if you are loading the the file with same name again.
You can go a step further to ensure the file names are more specific:
filename: (req, file, cb) => {
let fn = file.originalname.split(path.extname(file.originalname))[0] + '-' + Date.now() + path.extname(file.originalname);
cb(null, /* file.originalname */ fn);
}
I want to use HTML5 app cache in my MEAN app but I can't make it work in Firefox 36. It works in Chromium as expected. This is my file structure:
client
app.js
manifest.appcache
views/
index.html
about.html
server.js
index.html:
<!DOCTYPE html>
<html manifest="/manifest.appcache">
<head>
<meta charset="UTF-8">
</head>
<body>
About
</body>
</html>
manifest.appcache:
CACHE MANIFEST
#0
CACHE:
views/about.html
app.js
server.js:
var http = require("http");
var express = require("express");
var app = express();
app.get("/manifest.appcache", function (req, res) {
res.set("Content-Type", "text/cache-manifest");
res.set("Cache-Control", "no-store, no-cache");
res.set("Expires", "-1");
res.sendFile("/client/manifest.appcache", {root: __dirname});
});
app.get('/', function (req, res) {
res.sendFile('/client/views/index.html', {root: __dirname});
});
app.use(express.static(__dirname + '/client', { maxAge: 31557600000 }));
app.listen(8080);
When I go to localhost:8080, Firefox successfully fetches the manifest (which is not visible in the network tab of dev tools) but it does not store the files in the app cache (Preferences - Advanced - Network shows 0 bytes). It loads them from the standard system cache (I get 304).
I suspect that my routing somehow breaks the links in manifest.appcache but I had to prevent the manifest to be cached itself. I'm not an expert on Node.js and I'm confused by the fact that Chromium and Firefox behave differently. Any help will be appreciated.