req.file is undefined when uploading image from front end - javascript

I have checked other similar post but its still not working: Its giving me undefined when console.log. I also defined the multer middleware according to other posts so I don't know what happened. But when I upload an image through postman it works with returning an 201as expected. Any help is appreciated!
ReactJS function:
const UploadImageToBackend = async () => {
console.log(UploadedImage) //UploadedImage is something like /Users/.../.jpg
let formData = new FormData()
formData.append('profile',
{name : new Date() + "_profile", uri: UploadedImage, type:'image/jpg'})
try{
const res = await client.post('/upload-avatar',formData, {
headers:{
Accept : 'application/json',
authorization: 'JWT some JWT'
},
})
console.log(res.data)
}catch(error){
console.log(error.response.data) //gives "Error while uploading Image, try after some time" error
}
}
Backend Routes:
const fileFilter = (req,file,callback) => {
if (file.mimetype.startsWith('image')){
callback(null,true)
}else{
callback('invalid image file', false)
}
}
const storage = multer.diskStorage({})
const uploads = multer({storage, fileFilter})
router.post('/upload-avatar',isAuth, uploads.single('profile'),uploadProfile)
backend upload function (to Cloudinary)
exports.uploadProfile = async (req,res)=>{
const user = req.user
if (!user){
return res.status(401).json({success:false,message:"unauthorized access!"})
}else{
console.log(req.file.path) //undefined
try{
const upload_result = await cloudinary.uploader.upload(req.file.path, {
public_id: `${user._id}_profile`,
width:500,
height:500,
crop: 'fill'
})
await User.findByIdAndUpdate(user._id, {avatar: upload_result.url})
res.status(201).json({success:true,message: "Profile picture successfully uploaded"})
}catch (error){
res.status(500).json({success:false,message:
"Error while uploading Image, try after some time"})
}
}
}

create this function (to upload into Cloudinary), e.g. "lib/cloudinary.js" and add this code:
import cloudinary from "cloudinary";
cloudinary.config({
cloud_name: "YOUR_CLOUD_NAME",
api_key: "YOUR_API_KEY",
api_secret: "YOUR_API_SECRET",
});
const upload = {};
upload.subir = async (file) => {
try {
const res = await cloudinary.uploader.upload(file);
// return the secure url
return res.secure_url;
} catch (error) {
return error;
}
}
export default upload;
Now in your controller, e.g. add this code, do not forget to install express-fileupload:
import cloudinary from "../lib/cloudinary.js";
const upload = {};
upload.uploadProfile = async (req, res) => {
const a_file = await cloudinary.subir(req.files.a_file.tempFilePath);
// show the secure url, e.g.:
// https://res.cloudinary.com/xx/image/upload/yy/winter.jpg
console.log(a_file);
// ... more code
}
export default upload;
Now in your main application e.g., "app.js" add this code to use the express middleware for uploading files:
import express from 'express';
import fileUpload from 'express-fileupload';
const app = express();
app.use(express.json());
app.use(express.urlencoded({extended: true}));
app.use(fileUpload({useTempFiles: true}));
// ... more code
Test the function using postman and the file has been uploaded
  NOTE: Do not forget and
remember that this only is an alternative, exist anothers many ways i hope you understand and i hope it works for you

Related

Node app not writing to a file, no error logs

I am trying to use Capture-Website which saves screenshots of webpages to a file.
It used to work perfectly until I restarted the server.
Now the code runs without errors, but it does NOT save a screenshot to disk
Here is my code:
import http from 'http';
import url from 'url';
import querystring from 'querystring';
var mainURL;
const hostname = 'localhost';
const port = 8080;
import captureWebsite from 'capture-website';
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello World!\n');
var url_parts = url.parse(req.url, true);
var query = url_parts.query;
mainURL = query.url;
console.log(mainURL);
(async () => {
try {
await captureWebsite.file('https://'+mainURL, mainURL+".jpg", {
overwrite:true,
type: 'jpeg',
quality: 0.5,
width:1480,
height:800,
delay: 1
});
}
catch(err) {
console.log(err);
}
})();
});
There are no errors. I have also tried running pm2 logs - no errors there either.
Here is the file-writing code that belongs to the capture-website package:
captureWebsite.file = async (url, filePath, options = {}) => {
const screenshot = await internalCaptureWebsite(url, options);
await fs.writeFile(filePath, screenshot, {
flag: options.overwrite ? 'w' : 'wx',
});
};
Your problem is most likely that you can not use Slashes (/) in file names. This is because folders are seperated with slashes.

constant display of uploaded image React

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} />

Download JSON file from a node express server through my frontend

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);

Can't upload files to Node.js

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

Uploading documents, pdf's to google cloud using firebase. Get error

I'm trying to upload simple documents using busboy / express.js to google cloud.
I am getting this error.
Error: Cannot find module 'busboy/lib/types/node_modules/dicer'
and this is the code for the request.
// Upload a document for claim
exports.uploadDocument = (req, res) => {
const BusBoy = require("busboy");
const path = require("path");
const os = require("os");
const fs = require("fs");
const busboy = new BusBoy({ headers: req.headers });
let DocumentToBeUploaded = {};
let DocumentFileName;
// change this section to storing pdfs and docs etc
busboy.on("file", (fieldname, file, filename) => {
console.log(fieldname, file, filename);
const documentExtension = filename.split(".")[
filename.split(".").length - 1
];
// 32756238461724837.png
DocumentFileName = `${Math.round(
Math.random() * 1000000000000
).toString()}.${documentExtension}`;
const filepath = path.join(os.tmpdir(), DocumentFileName);
DocumentToBeUploaded = { filepath, mimetype };
file.pipe(fs.createWriteStream(filepath));
});
busboy.on("finish", () => {
admin
.storage()
.bucket()
.upload(DocumentToBeUploaded.filepath, {
resumable: false,
metadata: {
metadata: {
contentType: DocumentToBeUploaded
}
}
})
.then(() => {
const docUrl = `https://firebasestorage.googleapis.com/v0/b/${config.storageBucket}/o/${DocumentFileName}?alt=media`;
return db.doc(`/users/${req.Claim.ClaimId}`).update({ docUrl });
})
.then(() => {
return res.json({ message: "document uploaded successfully" });
})
.catch(err => {
console.error(err);
return res.status(500).json({ error: "something went wrong" });
});
});
busboy.end(req.rawBody);
};
Just trying to upload a very simple text document currently. Surely it can't be that difficult and I'm making a simple mistake somewhere.
Appreciate the help :)
You need to install busyboy:
npm i busboy
You can find more about this npm package in the following link:
https://www.npmjs.com/package/busboy

Categories

Resources