constant display of uploaded image React - javascript

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

Related

req.file is undefined when uploading image from front end

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

Why doesn't node-lame encode properly (nodeJS library)?

I've been trying to use the node-lame library to encode a file from the uploaded bitrate to 32 kbps to save space the same way I do it with sharp to compress my images.
My code first checks if the file is an audio file. If it is it then makes the encoder and it should encode it:
if (aud.test(user_file)){
const encoder = new Lame({
"output": req.file.path,
"bitrate": 32,
}).setFile(req.file.path);
await encoder
.encode()
.then(() => {})
.catch((error) => {
// Something went wrong
});
}
The problem is that it doesn't actually get encoded. I have also tried this in my .then but it doesn't help.
.then(data => {
fs.writeFileSync(req.file.path + '.mp3', data);
user_file = user_file + '.mp3';
fs.unlinkSync(req.file.path)
})
This is supposed to be a fairly simple library so I don't know what I'm doing wrong. I am trying to encode from file to file.
Also tried this:
const encoder = new Lame({
"output": user_file + '.mp3',
"bitrate": 32,
}).setFile(req.file.path);
I went ahead and wrote a demo for this. You can find the full repo here. I have verified this does work but keep in mind this is only a proof of concept.
This is what my Express server looks like:
const express = require('express');
const fs = require('fs');
const path = require('path');
const fileUpload = require('express-fileupload');
const Lame = require('node-lame').Lame;
const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(fileUpload());
// File upload path
app.post('/upload', async (req, res) => {
const fileToEncode = req.files.uploadedFile;
if (!fileToEncode) {
res.status(500).end();
return;
}
const filePath = path.resolve('./uploads', fileToEncode.name);
const outputPath = path.resolve('./uploads', fileToEncode.name + '-encoded.mp3');
// Save uploaded file to disk
await fileToEncode.mv(filePath);
try {
const encoder = new Lame({
output: outputPath,
bitrate: 8,
}).setFile(filePath);
await encoder.encode();
res.download(outputPath);
} catch (encodingError) {
console.error(encodingError);
res.status(500).send(encodingError);
}
// Removed files we saved on disk
res.on('finish', async () => {
await fs.unlinkSync(filePath);
await fs.unlinkSync(outputPath);
})
});
// Home page
app.get('*', (req, res) => {
res.status(200).send(`
<!DOCTYPE html>
<html>
<body>
<p id="status"></p>
<form method="post" enctype="multipart/form-data" action="/upload" onsubmit="handleOnSubmit(event, this)">
<input name="uploadedFile" type="file" />
<button id="submit">Submit Query</button>
</form>
<script>
async function handleOnSubmit(e,form) {
const statusEl = document.getElementById("status");
statusEl.innerHTML = "Uploading ...";
e.preventDefault();
const resp = await fetch(form.action, { method:'post', body: new FormData(form) });
const blob = await resp.blob();
const href = await URL.createObjectURL(blob);
Object.assign(document.createElement('a'), {
href,
download: 'encoded.mp3',
}).click();
statusEl.innerHTML = "Done. Check your console.";
}
</script>
</body>
</html>
`);
});
process.env.PORT = process.env.PORT || 3003;
app.listen(process.env.PORT, () => {
console.log(`Server listening on port ${process.env.PORT}`);
});

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

How to download a video file into browser

I made the routes below in express to download a video from youtube, but the video file goes into my project folder and it is not downloaded into the browser. It's like it works only in localhost.
This is my project folder:
node_modules
src
-app.js
static
-index.html
-styles.css
package.json
'THE FILE DOWNLOADED'
This is the code i made
const express = require('express')
const router = express.Router()
const fs = require('fs')
const ytdl = require('ytdl-core')
const youtube = require('simple-youtube-api')
router.post('/downloadByUrl', async (req, res) => {
let url = req.body.url
await downloadVideo(url)
return res.redirect('/')
})
router.post('/downloadByName', async (req, res) => {
let videoName = req.body.videoName
let youtubeClient = new youtube('MY YOUTUBE API KEY')
await youtubeClient.searchVideos(videoName, 1)
.then(results => {
downloadVideo('https://youtu.be/' + results[0].id)
})
.catch(console.log)
return res.redirect('/')
})
function downloadVideo(URL) {
let videoReadableStream = ytdl(URL)
ytdl.getInfo(URL, (err, info) => {
let title = info.title.replace('|', '').toString('ascii')
let stream = videoReadableStream.pipe(fs.createWriteStream(title + '.mp4'))
stream.on('finish', () => {
console.log('Finished')
})
})
}
module.exports = router
I want to host my website so i want to make possible the download of the file into the 'download' section of the browser.
How can I do that?

Categories

Resources