I would like to open in React a PDF file in a new tab when the URL is
blob:http://localhost:300/sample.pdf
Currently, it opens PDF file in a new tab, but the URL is
blob:http://localhost:3001/cfd3b31b-b4a8-4c65-aead-694fd27f12a8
My goal is to set the name to the pdf file in the URL (not download file)
What should be changed in the code in order to add the file name in the URL?
Code in React.js
import axios from "axios";
const ShowPDF = () => {
const getPdfFileAsBlob = async () => {
const url = `http://localhost:5001/pdf`;
//Force to receive data in a Blob Format
const config: any = {
responseType: "blob",
};
try {
const response = await axios.get(url, config);
//Create a Blob from the PDF Stream
const file = new Blob([response.data], {
type: "application/pdf",
});
//Build a URL from the file
const fileURL = URL.createObjectURL(file);
//Open the URL on new Window
window.open(fileURL);
} catch (error) {
console.log(error);
}
};
return <button onClick={getPdfFileAsBlob}>Show PDF</button>;
};
export default ShowPDF;
Code in Node.js - server.jsconst fs = require("fs");
const express = require("express");
const cors = require("cors");
const excel = require("exceljs");
const app = express();
app.use(cors());
app.use(express.json());
// GET
// Pdf route that will serve pdf
app.get("/pdf", (req, res) => {
const file = fs.createReadStream("./public/samplePDF.pdf");
file.pipe(res);
});
const PORT = process.env.PORT || 5001;
app.listen(PORT, () => {
console.log(`Server Started on Port ${PORT}`);
});
Related
I'm using Multer on server side for file upload
Midleware :
const util = require("util");
const path = require("path");
const multer = require("multer");
var storage = multer.diskStorage({
destination: (req, file, callback) => {
callback(null, path.join(`${__dirname}../../upload`));
},
filename: (req, file, callback) => {
const match = ["image/png", "image/jpeg"];
if (match.indexOf(file.mimetype) === -1) {
var message = `<strong>${file.originalname}</strong> is invalid. Only accept png/jpeg.`;
return callback(message, null);
}
var filename = `${Date.now()}-bezkoder-${file.originalname}`;
callback(null, filename);
}
});
var uploadFiles = multer({ storage: storage }).array("files", 10);
var uploadFilesMiddleware = util.promisify(uploadFiles);
module.exports = uploadFilesMiddleware;
Controller
const multipleUpload = async (req, res) => {
try {
await upload(req, res);
console.log('Check logs file ', req.Content - Type);
if (req.files.length <= 0) {
return res.send(`You must select at least 1 file.`);
}
return res.send(`Files has been uploaded.`);
} catch (error) {
console.log(error);
if (error.code === "LIMIT_UNEXPECTED_FILE") {
return res.send("Too many files to upload.");
}
return res.send(`Error when trying upload many files: ${error}`);
}
};
module.exports = {
multipleUpload: multipleUpload
};
Client capture Payload
My problem in upload event the server side show error messenger
Please help me to solve it.
Thanks
I have tried upload by axios is not problem but
I'm using the tool react Devextreme --> FileUploader . The supporter of devextreme did n't support server side .
I am working on my first ever MERN stack web app. I have used multer on my Node Js backend to upload files from my React frontend. I have been storing the files in the uploads folder which is outside of the frontend folder. I have been saving the image path in my MongoDB database. The idea was to use the image path to insert the image into my React frontend. The path stored in MongoDB is correct and images are also added in the uploads folder but they are not sowing on the frontend. I am actually storing paths of three images in an array using the same function. Below is my code
the image uploading function
const handleImageupload = async (event, Img1, Img2, Img3) => {
const file = event.target.files[0];
const formData = new FormData();
formData.append("image", file);
try {
setUploadLoading(true);
setUploadError(null);
const config = {
headers: {
"Content-type": "multipart/form-data",
// Authorization: `Bearer ${userInfo.token}`,
},
};
const { data } = await axios.post(
"http://localhost:5000/api/uploads/image",
formData,
config
);
if (Img1) {
setImage1(data.fileName);
}
if (Img2) {
setImage2(data.fileName);
}
if (Img3) {
setImage3(data.fileName);
}
setUploadLoading(false);
} catch (error) {
const errorMessage = error.response
? error.response.data.message
: error.message;
setUploadLoading(false);
setUploadError(errorMessage);
}
};
backend route of uploads
import express from "express";
import multer from "multer";
const router = express.Router();
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, "uploads/");
},
filename: function (req, file, cb) {
const uniqueSuffix = Date.now() + "-" + Math.round(Math.random() * 1e9);
const fileName =
file.fieldname + "-" + uniqueSuffix + path.extname(file.originalname);
cb(null, fileName);
},
});
const checkFileType = function (file, cb) {
const types = /jpg|png|jpeg/;
console.log(file.fieldname, file.fileName);
const isValidType = types.test(path.extname(file.originalname).toLowerCase());
const isValidMime = types.test(file.mimetype);
if (isValidType && isValidMime) {
cb(null, true);
} else {
cb(null, false);
}
};
const upload = multer({
storage: storage,
fileFilter: function (req, file, cb) {
checkFileType(file, cb);
},
});
router.post("/image", upload.single("image"), function (req, res) {
console.log(req.file);
res.json({ fileName: `/uploads/${req.file.filename}` });
});
export default router;
server.js
import dotenv from "dotenv";
import path from "path";
import colors from "colors";
import cors from "cors";
import { errorHandler, notFoundHandler } from "../middlewares/errorHandler.js";
import ConnectDb from "../config/db.js";
import laptopRoutes from "../routes/laptops.js";
import userRoutes from "../routes/userRoutes.js";
import uploadRoutes from "../routes/uploads.js";
import imagesRoutes from "../routes/images.js";
import orderRoutes from "../routes/order.js";
dotenv.config();
ConnectDb();
const app = express();
app.use(cors());
app.use(express.json());
app.get("/check", (req, res) => {
res.json({ message: "Api was called" });
});
app.use("/api/products", laptopRoutes);
app.use("/api/users", userRoutes);
app.use("/api/orders", orderRoutes);
app.use("/api/carouselimages", imagesRoutes);
app.use("/api/uploads", uploadRoutes);
const __dirname = path.resolve();
app.use("/uploads", express.static(path.join(__dirname, "/uploads")));
app.use(notFoundHandler);
app.use(errorHandler);
const port = process.env.PORT | 5000;
const mode = process.env.MODE;
app.listen(port, () => {
console.log(
`Application is running at port no ${port} in ${mode} mode`.inverse.cyan
);
});
How do I convert my app that is made with .pug to next app ? I have an app using .pug engine and I want to convert it into next.
This is the app.js but as I know next is different how do I do it? Because here my files are in views, and in views the files are in pages etc how do I do it? Is there any way or I have to code it all again?
const express = require('express');
const app = express();
const port = process.env.PORT || 3000;
const middleware = require('./middleware')
const path = require('path')
const bodyParser = require("body-parser")
const mongoose = require("./database");
const session = require("express-session");
const http = require('http');
const server = app.listen(port, () => console.log("Server listening on port " + port));
const io = require("socket.io")(server, { pingTimeout: 60000 });
app.set("view engine", "pug");
app.set("views", "views");
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static(path.join(__dirname, "public")));
app.use(session({
secret: "#########",
resave: true,
saveUninitialized: false
}))
// Routes
const loginRoute = require('./routes/loginRoutes');
const registerRoute = require('./routes/registerRoutes');
const logoutRoute = require('./routes/logout');
const postRoute = require('./routes/postRoutes');
const profileRoute = require('./routes/profileRoutes');
const uploadRoute = require('./routes/uploadRoutes');
const searchRoute = require('./routes/searchRoutes');
const messagesRoute = require('./routes/messagesRoutes');
const notificationsRoute = require('./routes/notificationRoutes');
// Api routes
const postsApiRoute = require('./routes/api/posts');
const usersApiRoute = require('./routes/api/users');
const chatsApiRoute = require('./routes/api/chats');
const messagesApiRoute = require('./routes/api/messages');
const notificationsApiRoute = require('./routes/api/notifications');
app.use("/login", loginRoute);
app.use("/register", registerRoute);
app.use("/logout", logoutRoute);
app.use("/posts", middleware.requireLogin, postRoute);
app.use("/profile", middleware.requireLogin, profileRoute);
app.use("/uploads", uploadRoute);
app.use("/search", middleware.requireLogin, searchRoute);
app.use("/messages", middleware.requireLogin, messagesRoute);
app.use("/notifications", middleware.requireLogin, notificationsRoute);
app.use("/api/posts", postsApiRoute);
app.use("/api/users", usersApiRoute);
app.use("/api/chats", chatsApiRoute);
app.use("/api/messages", messagesApiRoute);
app.use("/api/notifications", notificationsApiRoute);
app.get("/", middleware.requireLogin, (req, res, next) => {
var payload = {
pageTitle: "Home",
userLoggedIn: req.session.user,
userLoggedInJs: JSON.stringify(req.session.user),
}
res.status(200).render("home", payload);
})
io.on("connection", socket => {
socket.on("setup", userData => {
socket.join(userData._id);
socket.emit("connected");
})
socket.on("join room", room => socket.join(room));
socket.on("typing", room => socket.in(room).emit("typing"));
socket.on("stop typing", room => socket.in(room).emit("stop typing"));
socket.on("notification received", room => socket.in(room).emit("notification received"));
socket.on("new message", newMessage => {
var chat = newMessage.chat;
if(!chat.users) return console.log("Chat.users not defined");
chat.users.forEach(user => {
if(user._id == newMessage.sender._id) return;
socket.in(user._id).emit("message received", newMessage);
})
});
})
If you don't want to refactor all your pug template engine pages to next.js pages, then you can make the pug pages coexist with the next.js. You can make the next.js the default route, and place next.js code after all pug page routes. And you also need to refactor app.get("/", middleware.requireLogin, (req, res, next) => {...} to make sure next.js is the default route.
To apply this rule, you need a custom next.js server.
sample code
const express = require('express');
const next = require('next');
const port = 3000;
const dev = process.env.NODE_ENV !== 'production'; // use default NodeJS environment variable to figure out dev mode
const app = next({dev, conf});
const handle = app.getRequestHandler();
const server = express();
// all your pug page routes should be declared before `server.get('*'`.
server.get('*', authMiddleware(false), (req, res) => {
// pass through everything to NextJS
return handle(req, res);
});
app.prepare().then(() => {
server.listen(port, (err) => {
if (err) throw err;
console.log('NextJS is ready on http://localhost:' + port);
});
}).catch(e => {
console.error(e.stack);
process.exit(1);
});
In react hooks web app, how can we receive a csv file in the server side. The below is not working as I am getting the file undefined in server side. Could someone please advise ?
server.js
const multer = require('multer');
const bodyParser = require("body-parser");
const path = require('path');
app.use(express.static(path.join(__dirname, 'public')));
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'public/csv')
},
filename: function (req, file, cb) {
var ext = file.originalname.split('.').pop();
cb(null, file.fieldname + '-' + Date.now() + '.' + ext);
}
})
var upload = multer({ storage: storage });
app.put('/service/managenominees', upload.single('file'), async (req, res, next) => {
// csv file has two columns named Name, Email, I would like to receive value from those..
const data = req.file;
try {
if(req.body.file){
var name = req.file.Name;
var email = req.file.Email;
}
var nomineeData = {userName: name, userEmail: email};
res.status(200).send(nomineeData);
} catch (e) {
res.status(500).json({ fail: e.message });
}
});
manageNominee.js
import React, { useRef, useEffect, useState } from "react";
import Axios from "axios";
const ManageNominees = () => {
const [uploadFile, setUploadFile] = React.useState();
const [csvData, setCsvData] = useState([]);
const onChangeCsv = (e) => {
setCsvData(e.target.files[0]);
}
const submitForm = (data) => {
const dataArray = new FormData();
dataArray.append("uploadFile", data);
Axios.put("http://localhost:8000/service/managenominees", dataArray, {
headers: {
"Content-Type": "multipart/form-data"
}
})
.then((response) => {
// successfully uploaded response
})
.catch((error) => {
// error response
});
};
return (
<div>
<form onSubmit={submitForm} encType="multipart/form-data">
<h1>Upload Data</h1>
<input type="file" name="csvfile" onChange={onChangeCsv}/>
<button>Submit</button>
</form>
</div>
)
}
export default ManageNominees
There are two issues:
HTML attribute and the mutler upload option are different.
File values cant be accessed directly either convert the buffer and read the content or read the file (below code reads the file).
const multer = require('multer');
const bodyParser = require("body-parser");
const path = require('path');
const csv = require('csv-parser');
const fs = require('fs');
...
app.put('/service/managenominees', upload.single('csvfile'), (req, res, next) => {
console.log(req.file);
fs.createReadStream(req.file.path)
.pipe(csv())
.on('data', (data) => results.push(data))
.on('end', () => {
console.log(results);
// Result would be array as its CSV, iterate over the array and to get username and email id.
res.status(200).send(results);
});
});
Note: Code does not handle if the file does not exist.
Multer adds the uploaded files to req.file or req.files. My code works in Chrome as expected, but both req.file and req.files are empty in both Firefox (68.01) and Edge (44.17763.1.0).
Why does the request object doesn't contain the files in Firefox and Edge?
My multer config:
const path = require('path');
const uuidv4 = require('uuid/v4');
const multer = require('multer');
const projectRoot = require('./projectRoot');
// Allowed audio mime types
const audioMimeTypeToExt = {
'audio/wav': '.wav',
'audio/mp3': '.mp3',
};
// Allowed image mime types
const imageMimeTypeToExt = {
'image/jpeg': '.jpg',
'image/png': '.png'
};
// Storage options
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, path.join(projectRoot.path, '/public/tracks/'))
},
filename: function (req, file, cb) {
if (file) {
// New file name is uuid + extension (i.e. '10ba038e-48da-487b-96e8-8d3b99b6d18a.mp3')
cb(null, uuidv4() + audioMimeTypeToExt[file.mimetype])
} else {
console.log('File missing.');
}
}
});
// Filter options
const filter = function (req, file, cb) {
if (!(file.mimetype.toLowerCase() in audioMimeTypeToExt)) {
// Reject upload
cb(null, false);
}
// Accept upload
cb(null, true);
};
const uploadMiddleware = (req, res, next) => {
multer(
{
storage: storage,
fileFilter: filter,
limits: {fileSize: 50000000} //50mb
}
).array('tracks', 10)(req, res, function (err) {
if (err && err.code === "LIMIT_FILE_SIZE") {
return res.status(413).send(err.message);
}
next();
});
};
module.exports = {
audioMimeTypeToExt,
imageMimeTypeToExt,
uploadMiddleware: uploadMiddleware,
};
My route
const express = require('express');
const router = express.Router();
const sessionMiddleware = require('../middlewares/sessionMiddleware');
const {uploadMiddleware} = require('../config/multerConfig');
const uploadController = require('../controllers/uploadController');
router.post('/',
sessionMiddleware.requiredLogin,
uploadMiddleware,
uploadController.upload_post
);
module.exports = router;
My controller
const {processUploads} = require('../utilities/uploadsProcessor');
exports.upload_post = async function (req, res, next) {
if (req.files && req.files.length) { // req.files empty in Firefox and Edge
await processUploads(req);
console.log('Upload successful.');
res.status(200).end();
}
else {
res.status(404).end();
}
};
Thank you
Figured out what was going wrong. Firefox and Edge have different values in the file.mimetype field. For MP3 files, Chrome adds 'audio/mp3', while Firefox and Edge add 'audio/mpeg'. So my filter was filtering our files that don't contain 'audio/mp3' or 'audio/wav' mimetypes.