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
Related
Hell everyone,
Please i need help to understand what i am doing wrong.
My problem is : i'am trying to create an app that convert from .xml to json then from json to .xlsx after that download the file as excel sheet.
anyway, the first part of the project was successfully done.
but when i try to convert the file json that i converted from .xml. to xlsx not working at all.
so the files are :
ControllerXML2Json.js
working successfully and i can see the json data
const { json } = require('body-parser')
const fs = require('fs')
const xml2js = require('xml2js')
let jsonString
async function xml2json() {
try {
const xml = fs.readFileSync('src/data/dataset.xml')
const result = await xml2js.parseStringPromise(xml, { mergeAttrs: true })
jsonString = JSON.stringify(result, null, 4)
//console.log(json)
fs.writeFileSync('./public/data/result.json', jsonString)
//return jsonString
} catch (error) {
console.log(error)
}
}
module.exports = {
convert(req, res) {
let xmlFile = req.files.fileXML
xmlFile.mv('src/data/dataset.xml', function (err) {
if (err) {
return res.status(500).send(err)
} else {
xml2json()
}
})
res.redirect('/json')
}
}
ControllerJson2Xlsx.js
not working at all
//const { json } = require("body-parser");
const fs = require("fs");
const json2xlsx = require("json2xlsx");
const path = require("path");
//const fileName = "data.xlsx";
async function generateExcelFromJSON() {
try {
let data = JSON.parse(
fs.readFileSync("public/data/result.json", {
encoding: "utf8",
flag: "r",
})
);
let newWS = xlsx.utils.json_to_sheet(data);
let newWB = xlsx.utils.book_new();
xlsx.utils.book_append_sheet(newWS, newWB, "data");
await xlsx.writeFile("./public/data/data.xlsx", newWB);
// xlsx.writeFile(newWB, "./public/data/data.xlsx");
} catch (error) {
console.log(error);
}
}
module.exports = {
download(req, res) {
let jsonFile = req.files.fileJSON;
jsonFile.mv("public/data/result.json", function (err) {
if (err) {
return res.status(500).send(err);
} else {
json2xlsx();
}
});
res.redirect("/xlsx");
},
};
route.js
const express = require('express')
const ControllerJson2Xlsx = require('./controllers/ControllerJson2Xlsx')
const ControllerXML2Json = require('./controllers/ControllerXML2Json')
const route = express.Router()
route.get('/', (req, res) => res.render('index'))
route.get('/json', (req, res) => res.render('json'))
route.post('/convert', ControllerXML2Json.convert);
route.get("/single", ControllerJson2Xlsx.download);
// route.post('/teste', (req, res) => {
// return res.send(data)
// })
module.exports = route
I am getting the following errors when doing some changes but they never get resolved
node:internal/fs/utils:670 throw new ERR_INVALID_ARG_TYPE(propName, ['string', 'Buffer', 'URL'], path); ^
TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string or an instance of Buffer or URL. Received undefined
Sometime when I make some changes with help of internet this comes as in console log - post /api/product/create/6291eca0d8edbdf537a8eb4d - - ms - -
This is happening when I am trying to create a product and uploading an image over postman
Screenshots
1.app.js app.js
2.Product Route Product.js
3. Product Controller Product Controller.js
4.Product model Product Model
Code if the image does not open
Product Route-
const express = require("express")
const router = express.Router()
const { create } = require("../controllers/product")
const { requireSignin, isAdmin, isAuth } = require("../controllers/auth")
const { userById } = require("../controllers/user")
//Routes
router.post("/product/create/:userId", requireSignin, isAdmin, create)
router.param("userId", userById)
module.exports = router
Product Controller-
const formidable = require("formidable")
const _ = require("lodash")
const fs = require("fs")
const Product = require("../models/product")
const { errorHandler } = require("../helpers/dbErrorHandler")
exports.create = (req, res) => {
let form = new formidable.IncomingForm()
form.keepExtensions = true
form.parse(req, (err, fields, files) => {
if (err) {
return res.status(400).json({
err: "Image cannot be uploaded",
})
}
let product = new Product(fields)
if (files.photo) {
product.photo.data = fs.readFileSync(files.photo.path)
product.photo.contentType = files.photo.type
}
product.save((err, result) => {
if (err) {
console.log(err)
}
res.json(result)
})
})
}
I have a page where i display a static image. I want to display there the image i just uploaded. For that I have implemented file upload using express-fileUpload on my server and its working fine, it gets the photo and saves it into a folder, but i cannot display it on my page ( after page refresh it disappears).
How could i make this image remain even after refresh?
server.js code:
require('dotenv').config()
const express = require('express')
const mongoose = require('mongoose')
const cookieParser = require('cookie-parser')
const Years = require('./models/yearModel')
const Users = require('./models/userModel')
const bcrypt = require("bcrypt");
const cors = require('cors')
const fileUpload = require('express-fileupload')
const app = express()
app.use(express.json())
app.use(cors())
app.use(cookieParser())
app.use(fileUpload())
app.post('/upload', (req, res) => {
if (req.files === null) {
return res.status(400).json({ msg: 'No file uploaded' });
}
const file = req.files.file;
const fileName = "orar.jpg"+file.name
file.mv(`${__dirname}/client/public/uploads/${fileName}`, err => {
if (err) {
console.error(err);
return res.status(500).send(err);
}
res.json({ fileName: file.name, filePath: `/uploads/${file.name}` });
});
});
const PORT = process.env.PORT || 5000
app.listen(PORT, () => {
console.log('Server running on port: ', PORT)
})
And this is the code of my page where i want to display the image ( without return markup ):
const Orar = () => {
const [file, setFile] = useState("");
const [filename, setFilename] = useState("Choose File");
const [uploadedFile, setUploadedFile] = useState({});
const onChange = (e) => {
setFile(e.target.files[0]);
setFilename(e.target.files[0].name);
};
const onSubmit = async (e) => {
e.preventDefault();
const formData = new FormData();
formData.append("file", file);
try {
const res = await axios.post("/upload", formData, {
headers: {
"Content-Type": "multipart/form-data",
}
});
const { fileName, filePath } = res.data;
setUploadedFile({ fileName, filePath });
setMessage("File Uploaded");
} catch (err) {
if (err.response.status === 500) {
setMessage("There was a problem with the server");
} else {
setMessage(err.response.data.msg);
}
}
};
I don't know the architecture of your website and database so if you stock only one image inside your website, you can store the id of the uploaded image inside your browser localstorage: link here (I don't recommend this practice).
A good practice is to store the id or path of your uploaded image inside your database. For example, if you want to edit or display a profile picture, go to your user schema (in your db), stock the id or the path of the uploaded image here. Then when you'll call the #GET /users/:userId, you will retrieve the image id or the image path (depends on which of them you stock).
If you retrieve the link to your image, just do that inside your html code:
<img src={myImageLocation} alt={myImageAlt} />
If you stock your image on a dedicated server (it's what you're doing), you can only retrieve the image id and render the image like that:
<img src={`${serverPATH}/${imageId}`} alt={myImageAlt} />
I have stored the file after uploading it to the downloads folder in my project directory.
I want to download that saved file from the frontend.
When I click on the download button, it doesn't fetch the file.
And when I go to http://localhost:5000/download on the express app, I got this error message
Error: Can't set headers after they are sent.
Express Server Code:
app.get('/download', (req, res) => {
res.send('file downloaded')
const file = './downloads/output.yml';
res.download(file, 'openapi.yml', (err) => {
if (err) {
console.log(err)
} else {
console.log('file downloaded')
}
});
});
Frontend App code:
HTML:
<button class="download-btn">download</button>
Script:
const handleDownload = async () => {
const res = await fetch("https://cors-anywhere.herokuapp.com/http://localhost:5000/download");
const blob = await res.blob();
download(blob, 'output.yml');
}
downloadBtn.addEventListener('click', handleDownload);
Folder Structure:
Update:
Server.js
const uploadFiles = async (req, res) => {
const file = await req.files[0];
console.log(file)
postmanCollection = file.path;
outputFile = `downloads/${file.filename}.yml`
convertCollection();
res.json({ message: "Successfully uploaded files" });
}
app.post("/upload_files", upload.array("files"), uploadFiles);
Anyone please help me with this.
You are already using res.send ,which sends the response headers back to client ,which ends the request response cycle ,and when you try to do res.download it throws error. Use instead
app.get('/download', (req, res) => {
const file = './downloads/output.yml';
res.download(file, 'openapi.yml', (err) => {
if (err) {
console.log(err)
} else {
console.log('file downloaded')
}
});
});
res.send('file downloaded')--->remove this line
You need to update your js code as well
const handleDownload = async () => {
const res = await fetch("https://cors-anywhere.herokuapp.com/download"); //http://localhost:5000--->this is not required
const blob = await res.blob();
download(blob, 'output.yml');
}
downloadBtn.addEventListener('click', handleDownload);
I'm using n-readline npm package to read text files from the server.
I have a use case, where I had to read at least 300MB of data from those text files and will be using Redis or Mongoose to save around 40mb of data to be transferred to the browser where I use vue to process that or load data whenever needed.
Now I'm running into a problem where I'm unable to get the results when I call that function for the first time, if I call that again, the function provides me with results.
const express = require('express');
const multer = require('multer');
const fs = require('fs');
const NreadLine = require('n-readline');
const app = express();
var asyncres = [];
var lines = []
const upload = multer({ storage });
async function nreadline(){
let linenumbers = [];
var rl = new NreadLine({
filepath: './uploads/6789765/serverout1.txt',
limit: 50
});
await rl.start();
await rl.on('line', (line, linenumer) => {
linenumbers.push(linenumer);
});
await rl.on('end', () => {
console.log('done');
asyncres = [...linenumbers];
});
//This is where I'm expecting the results to be returned
return asyncres;
}
function getresults() {
let ress = nreadline();
console.log(ress);
return ress;
}
// Express APIs defined below
app.post('/upload', upload.single('file'), (req, res) => {
res.json({ "status": "success", file: req.file });
});
// API for multiple form upload
app.post('/multiple', upload.array('files'), (req, res) => {
// ticket = req.body.ticket
res.json({ "status": "success", files: req.files });
});
//Get Request for reading the files
app.get('/reader', (req, res) => {
let results = getresults();
res.json({ "status": results });
});
app.listen(port, () => {
console.log("running on 3344 port");
});
Please Help. I am not sure what I'm doing wrong.
To answer my own question, I found another npm package, that kinda solves my problem.
The package name is n-readlines and below the code that I modified.
const lineByLine = require('n-readlines');
function nreadline(filePath){
let logs = [];
try{
let rl = new lineByLine('./uploads/6789765/serverout0.txt');
let line;
while(line=rl.next()){
logs.push(line.toString('utf8'));
}
return logs;
}catch(err){
}