I am trying to upload files from my website to an amazon ec2 instance, i am using the IP Address; however, the connection is timing out. I have the private key, but am not using it in any way, so far.
what do I need to do to keep this from timing out, and successfully upload my items/overwrite old items (with the same name), and where should the code be added, i am assuming for the private key...?
I have attempted specifying the folder, using http instead of https, updating my server
onclick handler
onClickHandler = () => {
const data = new FormData();
data.append('file', this.state.selectedFile);
axios.post("https://xx.xxx.xxx.xx/upload", data, {
// receive two parameter endpoint url ,form data
}).then(res => { // then print response status
console.log(res.statusText)
})
};
Server
var express = require('express');
var app = express();
var multer = require('multer');
var cors = require('cors');
app.use(cors());
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'public/upload')
},
filename: function (req, file, cb) {
cb(null, file.originalname )
}
});
var upload = multer({ storage: storage }).single('file');
app.post('/upload',function(req, res) {
upload(req, res, function (err) {
if (err instanceof multer.MulterError) {
return res.status(500).json(err)
} else if (err) {
return res.status(500).json(err)
}
return res.status(200).send(req.file)
})
});
app.listen(8000, function() {
console.log('App running on port 8000');
});
i need help figuring out what i am missing, and where to put it, Thank you to anyone who is able to help me out!
Related
I want to build an API "/upload/excel" that will allow users to import an excel file and inside it after receiving an excel file, it will read its field and save it into database.
How to achieve this?
I am using multer for uploading the file and xlsx to process it and mongodb as a database (mongoose for the model):
Lead is the data model, you have to add the Excel sheet columns name. See mongoose documentation for more information
const express = require("express");
const multer = require("multer");
const connectDB = require("./config/db");
const Lead = require("./models/Lead");
connectDB();
const uploadXLSX = async (req, res, next) => {
try {
let path = req.file.path;
var workbook = XLSX.readFile(path);
var sheet_name_list = workbook.SheetNames;
let jsonData = XLSX.utils.sheet_to_json(
workbook.Sheets[sheet_name_list[0]]
);
if (jsonData.length === 0) {
return res.status(400).json({
success: false,
message: "xml sheet has no data",
});
}
let savedData = await Lead.create(jsonData);
return res.status(201).json({
success: true,
message: savedData.length + " rows added to the database",
});
} catch (err) {
return res.status(500).json({ success: false, message: err.message });
}
};
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, "uploads");
},
filename: function (req, file, cb) {
cb(null, Date.now() + "-" + file.originalname);
},
});
const upload = multer({ storage: storage });
app.post("/upload", upload.single("xlsx"), uploadXLSX);
const port = process.env.PORT || 5000;
const server = app.listen(port, () => {
console.log("app running on port", port);
});
So from here when you make a call to localhost:5000/upload with postman see picture below
You can upload a file through multer or formidable
https://www.npmjs.com/package/multer
https://www.npmjs.com/package/formidable
And you can read xl files though any one of these below npm packges
https://www.npmjs.com/package/xlsx
https://www.npmjs.com/package/read-excel-file
The below is a rudimentary file upload utility. It handles React / Axios API POSTs satisfactorily. Files get uploaded to the ~uploads folder under root on the server. How does one add API DELETE handling capability to it? Envision a use case where a user uploads an attachment to a blog post and then deletes the attachment from the blog post. Have had issues locating an example.
var cors = require('cors');
var express = require('express');
var multer = require('multer')
var app = express();
app.use(cors());
// Parse JSON bodies (as sent by API clients)
app.use(express.json());
var storage = multer.diskStorage(
{
destination: function (req, file, cb)
{
cb(null, 'fileuploads');
},
filename: function (req, file, cb)
{
cb(null, file.originalname );
}
})
var upload = multer({ storage: storage }).array('file')
app.post('/upload',function(req, res)
{
upload(req, res, function (err)
{
if (err instanceof multer.MulterError)
{
return res.status(500).json(err)
}
else if (err)
{
return res.status(500).json(err)
}
return res.status(200).send(req.file)
})
});
app.listen(8001, function() {
console.log('App running on port 8001');
});
EDIT:
Modified app.delete(...) to the below, which successfully deletes the file but after about a minute throws this error in the console: [Error: ENOENT: no such file or directory, unlink '<PATH VALUE>']
app.delete('/writer/:file_to_delete', async (req, res) =>
{
const path = 'assets/uploads/' + req.params.targetFile;
console.log(path);
try
{
fs.unlink(path)
// NOTE: `fs.unlinkSync(path)` does the same thing
console.log('File deleted!');
return res.status(200);
}
catch(err)
{
console.error(err)
return res.status(500).json(err)
}
});
I found a way forward. The code is below but I'm happy to hear about better ways to do it:
// NOTE: `file_name` values are obfuscated and uniquely generated by the client.
// The actual file name is in data storage.
app.post('/delete/:file_name', (req, res) =>
{
const theFile = 'attachments/' + req.params.file_name;
var resultHandler = function(err) {
if(err) {
console.log("file delete failed", err);
return res.status(500).json(err)
}
console.log("file deleted");
return res.status(200).send({data: req.params.file_name + ' deleted'});
}
fs.unlinkSync(theFile, resultHandler);
});
I'm trying to make my own upload service, and I want to be able to upload a file in a local folder on my server but also on my mongoDB cloud service (Atlas).
So far, I've done both services separately and they work fine (I made a Node app for uploading files to mongo Atlas and another Node app for uploading files to the server). But now, I would like to unifiy these two into a single node app, where after each POST request, the file gets sent to both Atlas as well as the local folder. I'm using multer and gridfs.
The first attempt was to make two "file-input" fields on my index.html file, and each of those with two different POST requests: one to '/upload' which sends the file to Atlas and the second one to '/uploaddisk' which sends the file to disk. However, the second post request doesn't work (it throws me the error every time I want to submit my file). Uploading the file to mongoDB seems to work just fine every time.
Any ideas how can I do this on a single POST ? Thank you in advance!
Here is the code that I wrote for my server.js app:
//mongo DATA
const dbURI =
"myc-atlas-credentials";
mongoose.Promise = global.Promise;
// mongoose.connect(bdURI, { useNewUrlParser: true, useUnifiedTopology: true });
const conn = mongoose.createConnection(dbURI, {
useNewUrlParser: true,
useUnifiedTopology: true
});
//init gfs
let gfs;
conn.once("open", () => {
//initialize the stream
gfs = Grid(conn.db, mongoose.mongo);
gfs.collection("uploads");
});
//creating the storage engine for MONGO
const storage = new GridFsStorage({
url: dbURI,
file: (req, file) => {
return new Promise((resolve, reject) => {
const filename = file.fieldname + '-' + Date.now() + path.extname(file.originalname);
const fileInfo = {
filename: filename,
bucketName: "uploads"
};
resolve(fileInfo);
});
}
});
const upload = multer({ storage: storage });
//set storage engine with multer for disk
const diskstorage = multer.diskStorage({
destination: function(req, file, cb) {
cb(null, path.join(__dirname + '/uploads/'));
},
filename: function(req, file, cb) {
cb(null, file.fieldname + '-' + Date.now() + path.extname(file.originalname));
}
});
const diskupload = multer({ storage: diskstorage });
//route for POST - upload data to mongo
app.post('/upload', upload.single('file'), (req, res) => {
console.log({ file: req.file });
// res.json({ file: req.file });
res.redirect('/');
});
//route for POST - upload data to disk
app.post('/uploaddisk', diskupload.single('file'), (req, res, next) => {
const file = { file: req.file };
if (!file) {
const error = new Error('Please upload a file');
error.httpStatusCode = 400;
return next(error);
}
res.redirect('/');
});
You can try it like this:
function fileUpload(req, res, next) {
upload.single('file')(req, res, next);
diskupload.single('file')(req, res, next);
next();
}
//route for POST - upload data to mongo
app.post('/upload', fileUpload, (req, res) => {
console.log({ file: req.file });
// res.json({ file: req.file });
res.redirect('/');
});
I've written a react app that makes use of the FilePond file uploader but am having trouble getting multer to accept the request from filepond, it always returns a 500 error.
If I use a standard file upload control the request is accepted by the server and the file uploads fine.
Does anyone have any thoughts on what might be causing this?
Thanks
This is my server.js code:
var express = require('express');
var app = express();
var multer = require('multer')
var cors = require('cors');
app.use(cors())
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'public')
},
filename: function (req, file, cb) {
cb(null, Date.now() + '-' +file.originalname )
}
})
var upload = multer({ storage: storage }).array('file')
app.get('/',function(req,res){
return res.send('Hello Server')
})
app.post('/upload', function(req, res) {
upload(req, res, function (err) {
if (err instanceof multer.MulterError) {
return res.status(500).json(err)
// A Multer error occurred when uploading.
} else if (err) {
return res.status(500).json(err)
// An unknown error occurred when uploading.
}
res.send([req.files[0].filename]);
return res.status(200).send(req.file)
// Everything went fine.
})
});
app.listen(8000, function() {
console.log('App running on port 8000');
});
It simply doesn't save anything to the destination folder i specified.
i tried {storage:storage} instead of {dest: 'storage/'} but it didn't work either.
the image data is actually sent to the server as its console logged. and the dest i specified is created by default but remain empty.
const express = require('express');
const app = express();
const multer = require('multer');
let storage = multer.diskStorage({
destination: '/public/my-uploads',
filename: function (req, file, cb) {
cb(null, file.fieldname + '-' + Date.now())
}
});
const upload = multer({dest:'storage/'}).single('file');
app.post('/upload', upload, (req , res) => {
console.log(req.files) // this does log the uploaded image data.
})
***** EDIT ******
HTML
<form onSubmit={this.upload} enctype='multipart/form-data'>
<input type='file' name='image' />
<input type='submit' value='upload' />
</form>
JS
upload(e){
e.preventDefault();
const file = e.target[0].files[0];
console.log(file)
const fm = new FormData();
fm.append('file', file);
console.log(fm)
axios.post('/upload', fm);
}
POSTMAN
Try to catch the error my calling the middleware yourself:
var upload = multer().single('avatar')
app.post('/upload', function (req, res) {
upload(req, res, function (err) {
if (err) {
// An error occurred when uploading
return
}
// Everything went fine
})
})
Also, change the storage to this:
let storage = multer.diskStorage({
destination: function(req, file, ca) {
cb(null, '/public/my-uploads');
}
filename: function (req, file, cb) {
cb(null, file.fieldname + '-' + Date.now())
}
});
It's been a while, the issue was that I wasn't using the multer middleware at all so the callback code for handling the image was never executed.
I didn't know much about how express worked back then.
Seems you are not using the storage variable and use a function for the destination key, as written in the documentation, also you need to pass your file in the input field named field otherwise multer can't store the file, create an storage folder on the same level as the code :
const http = require('http')
const port = 3000
const express = require('express');
const app = express();
const multer = require('multer');
const server = http.createServer(app)
let storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './storage')
},
filename: function (req, file, cb) {
cb(null, file.fieldname + '-' + Date.now())
}
});
const upload = multer({ storage }).single('file');
app.post('/upload', upload, (req, res) => {
console.log(req.files) // this does log the uploaded image data.
})
// bind the server on port
server.listen(port, (err) => {
if (err) {
return console.log('something bad happened', err)
}
console.log(`server is listening on ${port}`)
})
The name of the "single" in ...single('file') must match the name in the input (containing the file) <input type="file" name='image' /> - and it does not in your example.
Change the multer-part to this ...single('image') - as in the input name='image'
Try this File Storage For Save image in Local
const fileStorage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, "images");
},
filename: (req, file, cb) => {
cb(
null,
new Date().toISOString().replace(/:/g, "-") + "-" + file.originalname
);
},
});