I want to save images after resize so used sharp package but dont small image size.Iadded await sharp(uploadImage.name).resize(600, 600); line after save folder What am I missing?
const path = require('path');
const fs = require('fs');
const AdminBro = require('admin-bro');
const sharp=require('sharp');
/** #type {AdminBro.After<AdminBro.ActionResponse>} */
const after = async (response, request, context) => {
const { record, uploadImage } = context;
if (record.isValid() && uploadImage) {
// console.log(uploadImage.name);
await sharp(uploadImage.name).resize(600, 600);
const filePath = path.join('uploads', record.id().toString(), uploadImage.name);
await fs.promises.mkdir(path.dirname(filePath), { recursive: true });
await fs.promises.rename(uploadImage.path, filePath);
await record.update({ imagePath: `/${filePath}` });
}
return response;
};
/** #type {AdminBro.Before} */
const before = async (request, context) => {
if (request.method === 'post') {
const { uploadImage, ...otherParams } = request.payload;
// eslint-disable-next-line no-param-reassign
context.uploadImage = uploadImage;
return {
...request,
payload: otherParams,
};
}
return request;
};
module.exports = { after, before };
const filePath = path.join('uploads', record.id().toString(), uploadImage.name);
await fs.promises.mkdir(path.dirname(filePath), { recursive: true });
await sharp(uploadImage.path).withMetadata().resize(600,600).toFile(filePath);//here added correct paths but now although it saved image, doesnt reduce imageSize
You are not writing the processed image to a file.
Let's say this is your storage path:
const outputPath = __dirname + `/../storage/myImage.jpeg`;
You can give that path to sharp
await sharp('path/of/originalImage').withMetadata().resize(600, 600).toFile(outputPath);
And I highly recommend you to use withMetaData() otherwise you lose your images metaData
Related
Hi I am trying to insert data in the database using a POST Request but the data is not being inserted.
On further investigation I found that to upload form-data, busboy needs to be used for image upload in firebase functions but I am not able to find a solution for using busboy with post method.
Hence if someone can please help me resolve this issue.
Below is the code for reference.
app.js
const express = require('express')
//const router = true;
const router = new express.Router()
const userInfo = require('../models/userProfile')
const multer = require('multer');
var fs = require('fs');
var path = require('path');
var JSONStream = require('JSONStream');
const planCheck = require('../models/planDetails');
const login = require('../models/login_creditionals');
const {Storage} = require('#google-cloud/storage');
const {format} = require('util');
const busboy = require('busboy');
const storage = new Storage({
projectId: "biz-1",
keyFilename: "/Users/akm/pixNodes/functions/pixbiz-65a402.json"
});
const bucket = storage.bucket("gs://biz-1");
const upload = multer({
storage: multer.memoryStorage(),
limits: {
fileSize: 10 * 1024 * 1024
}
})
const uploadImageToStorage = (file) => {
return new Promise((resolve, reject) => {
if (!file) {
reject('No image file');
}
let newFileName = `${Date.now() + path.extname(file.originalname)}`;
let fileUpload = bucket.file(newFileName);
const blobStream = fileUpload.createWriteStream({
metadata: {
contentType: file.mimetype
}
});
blobStream.on('error', (error) => {
reject('Something is wrong! Unable to upload at the moment.');
});
blobStream.on('finish', () => {
// The public URL can be used to directly access the file via HTTP.
const url = format(`https://storage.googleapis.com/${bucket.name}/${fileUpload.name}`);
resolve(url);
});
blobStream.end(file.buffer);
});
}
router.post('/userprofile/check' ,upload.single('profile_pic'), async (req,res) => {
var reqFiles;
var reqFilesUrl;
reqFiles = req.file;
if(reqFiles) {
// const imagerUrl = await uploadImageToStorage(reqFiles)
reqFilesUrl = imagerUrl;
console.log(reqFilesUrl);
const notify = new userInfo({
userId: req.body.userId,
mobile_number : req.body.mobileNumber,
profile_pic: reqFilesUrl
})
try {
console.log('success insert data');
await notify.save((err,post) => {
if(err) {
console.log(err);
}
//console.log('data saved', post);
res.status(201).send(post);
});
// });
// res.status(201).send();
console.log('201');
} catch(e) {
//res.status(401);
return res.send(e);
}
This is my code to get a dicom image from Google Cloud. It works well, but the image is lossy.
router.get("/dicomWebRetrieveInstance/dcmfile", async (req, res, next) => {
const writeFile = util.promisify(fs.writeFile);
emphasized textconst fileName = 'rendered_image.jpeg';
const cloudRegion = "us";
const projectId = "neurocaredicom";
const datasetId = "System_1";
const dicomStoreId = "Site_1A";
const studyUid = "1.2.276.0.7230010.3.1.2.296485376.1.1521713579.1849134";
const seriesUid = "1.2.276.0.7230010.3.1.3.2`enter code here`96485376.1.1521713580.1849651";
const instanceUid = "1.2.276.0.7230010.3.1.4.296485376.1.1521713580.1849652";
const parent = `projects/${projectId}/locations/${cloudRegion}/datasets/${datasetId}/dicomStores/${dicomStoreId}`;
const dicomWebPath = `studies/${studyUid}/series/${seriesUid}/instances/${instanceUid}/rendered`;
const request = {parent, dicomWebPath};
const rendered =
await healthcare.projects.locations.datasets.dicomStores.studies.series.instances.retrieveRendered(
request,
{
headers: "application/octet-stream; transfer-syntax=* ",
responseType: 'arraybuffer',
}
);
const fileBytes = Buffer.from(rendered.data);
await writeFile(fileName, fileBytes);
var options = {
root: path.join(__dirname),
};
// read binary data
var bitmap = fs.readFileSync(fileName);
// convert binary data to base64 encoded string
res.status(200).sendFile(fileName, options, function (err) {
if (err) {
next(err);
} else {
console.log(
`Retrieved rendered image and saved to ${fileName} in current directory`
);
}
});
});
Any solution to that problem would be appreciated, so anyone can help.
I can't go to another ejs page.
Description
The link to go to the ejs page does not work
I have an existing project... Everything works in it...
Example: a transition is made from Index -> to a subpage.
In the current state of the project, the subpage is located at localhost:3000/0/articles/14
The subpage is filled with data from the database.
I did.
created my own Index page;
Index page- opens;
created my own About Subpage;
Result: switching from the Index page to About does not work.
Index.ejs
<h1>Index page</h1>
<a href="/about" >About-1. Описание</a> </br>
<a href="http://localhost:3000/About/" >About-2. Описание</a>
I added to the file routes.js
.get('/about', (req, res) => {
res.render('about');
})
The whole code routes.js
const multer = require('multer');
const rand = require('randomstring');
const filesStorage = multer.diskStorage({
destination: (req, file, next) => {
next(null, 'static/uploads/files');
},
filename: (req, file, next) => {
const ext = file.originalname.split('.').pop();
next(null, rand.generate({
length: 32,
charset: 'alphabetic'
}) + '.' + ext);
}
});
const filesUpload = new multer({
storage: filesStorage
});
const site = {
main: require('./controllers/main')
};
const cms = {
articles: require('./controllers/cms/articles'),
files: require('./controllers/cms/files'),
lang: require('./controllers/cms/lang'),
slideshow: require('./controllers/cms/slideshow')
};
module.exports = (app, passport) => {
app
.get('/', site.main.lang)
.get('/video', site.main.video)
.get('/slideshow', site.main.slideshow)
.get('/:lang', site.main.index)
/*articles*/
.get('/:lang/articles', site.main.index)
.get('/:lang/articles/:id', site.main.article)
.get('/:lang/panomuseum', site.main.panomuseum)
.get('/:lang/panomuseum/2', site.main.panomuseum2)
.get('/:lang/panotheatre', site.main.panotheatre)
/*My*/
// .get('/:lang/articles', site.main.index)
.get('/Index', site.main.index)
.get('/history', site.main.history)
// .get('/history', (req, res) => {
// res.render('history');
// })
.get('/about', (req, res) => {
res.render('about');
})
;
app
.get('/cms/lang', cms.lang.index)
.post('/cms/lang', filesUpload.any(), cms.lang.save)
.get('/cms/:lang/articles', cms.articles.index)
.post('/cms/articles/saveOrder', cms.articles.saveOrder)
.get('/cms/:lang/articles/add', cms.articles.add)
.post('/cms/:lang/articles/add', filesUpload.any(), cms.articles.postAdd)
.get('/cms/:lang/articles/:id/edit', cms.articles.edit)
.post('/cms/:lang/articles/:id/edit', filesUpload.any(), cms.articles.postEdit)
.get('/cms/:lang/articles/:id/delete', cms.articles.delete)
.get('/cms/:lang/articles/:id', cms.articles.subArticle)
.get('/cms/:lang/articles/add/:id', cms.articles.add)
.post('/cms/files/delete', cms.files.delete)
.post('/cms/files/saveFile', filesUpload.single('file'), cms.files.saveFile)
.post('/cms/files/saveThumb', filesUpload.single('thumb'), cms.files.saveThumb)
.get('/cms/slideshow', cms.slideshow.index)
.post('/cms/slideshow/save', filesUpload.any(), cms.slideshow.save);
return app;
controllers\main.js
const db = require('../db');
const fs = require('fs');
const path = require('path');
const config = require('../config.js');
class Main {
async video(req, res, next) {
const videoFolder = './static/video'
let videos = []
fs.readdirSync(videoFolder).forEach((file) => {
let extension = path.extname(file)
let filename = path.basename(file, extension)
videos.push({
file,
filename: parseInt(filename),
})
})
videos = videos.sort((a, b) => {
return a.filename - b.filename
})
return res.render('video', {
domain: config.express.domain,
videos,
})
}
async panomuseum(req, res) {
const article = await db.article.getByID(req.params.lang);
const sub = await db.article.getRoot(req.params.lang);
const files = await db.files.getByOwnerId(req.params.lang);
const lang = await db.lang.getById(req.params.lang);
return res.render('panomuseum', {
article,
sub,
files,
lang
});
}
async panomuseum2(req, res) {
const article = await db.article.getByID(req.params.lang);
const sub = await db.article.getRoot(req.params.lang);
const files = await db.files.getByOwnerId(req.params.lang);
const lang = await db.lang.getById(req.params.lang);
return res.render('panomuseum2', {
article,
sub,
files,
lang
});
}
async panotheatre(req, res) {
const article = await db.article.getByID(req.params.lang);
const sub = await db.article.getRoot(req.params.lang);
const files = await db.files.getByOwnerId(req.params.lang);
const lang = await db.lang.getById(req.params.lang);
return res.render('panotheatre', {
article,
sub,
files,
lang
});
}
async index(req, res) {
const article = await db.article.getByID(req.params.lang);
const sub = await db.article.getRoot(req.params.lang);
const files = await db.files.getByOwnerId(req.params.lang);
const lang = await db.lang.getById(req.params.lang);
const timeout = await db.settings.getByID("timeout");
const caption = await db.settings.getByID("caption");
return res.render("index", {
article,
sub,
files,
lang,
timeout,
caption,
domain: req.app.get("domain"),
});
}
// async history(req, res) {
// // const article = await db.article.getByID(req.params.lang);
// // const sub = await db.article.getRoot(req.params.lang);
// // const files = await db.files.getByOwnerId(req.params.lang);
// // const lang = await db.lang.getById(req.params.lang);
// // const timeout = await db.settings.getByID("timeout");
// // const caption = await db.settings.getByID("caption");
// return res.render("history", {
// domain: req.app.get("domain")
// });
// }
async history(req, res) {
console.log('Request for history page recieved');
return res.render("history");
}
async about(req, res) {
console.log('Request for about page recieved');
return res.render("about");
}
async menu(req, res) {
return res.render("menu", {
domain: req.app.get("domain"),
});
}
async slideshow(req, res) {
const slideshow = await db.files.getSlideshow();
const timer = await db.settings.getByID("timer");
return res.render("slideshow", {
slideshow,
timer,
domain: req.app.get("domain"),
});
}
async slide(req, res) {
const slideshow = await db.files.getByID(req.params.id);
const timer = await db.settings.getByID("timer");
return res.render("slideshow", {
slideshow: [slideshow],
timer,
domain: req.app.get("domain"),
});
}
async article(req, res) {
const article = await db.article.getByID(req.params.id);
const sub = await db.article.getSub(req.params.id);
const files = await db.files.getByOwnerId(req.params.id);
const id = req.params.id;
const lang = await db.lang.getById(req.params.lang);
const timeout = await db.settings.getByID("timeout");
const caption = await db.settings.getByID("caption");
return res.render("index", {
id,
article,
sub,
files,
lang,
timeout,
caption,
domain: req.app.get("domain"),
});
}
async lang(req, res) {
const langs = await db.lang.getAll();
let activeCount = 0;
for (let lang of langs) {
if (lang.value == 1) {
activeCount++;
}
}
if (activeCount == 0) {
return res.redirect("/0");
} else if (activeCount == 1) {
for (let lang of langs) {
if (lang.value == 1) {
return res.redirect("/" + lang.id);
}
}
}
const timeout = await db.settings.getByID("timeout");
return res.render("lang", {
langs,
timeout,
});
}
async openSlide(req, res) {
console.log("openSlide");
let files = await db.files.getSyncSmartHome();
parentIO.sockets.in("client").emit("goToUrl", {
message: "/slide/" + files[parseInt(req.params.id)].id,
});
return res.json({
success: true,
});
}
async openSlideshow(req, res) {
console.log("open slideshow");
parentIO.sockets.in("client").emit("goToUrl", {
message: "/slideshow",
});
return res.json({
success: true,
});
}
}
module.exports = new Main();
I've written a cloud function which resizes images after uploading to cloud storage then returns the signed URL for the image uploaded but when I try to write the URL afterwards to firestore I get a PERMISSION_DENIED: Missing or insufficient permissions error. Is there a way around this without changing the firestore rules to allow anyone read/write access?
Below is the code:
import * as functions from "firebase-functions";
import * as admin from "firebase-admin";
import * as fs from "fs-extra";
import { tmpdir } from "os";
import { join, dirname } from "path";
import * as sharp from "sharp";
admin.initializeApp({
credential: admin.credential.applicationDefault()
});
const gcs = admin.storage();
const db = admin.firestore();
export const generateThumbs = functions.storage
.object()
.onFinalize(async object => {
const bucket = gcs.bucket(object.bucket);
const filePath = object.name as string;
const fileName = filePath.split("/").pop();
const bucketDir = dirname(filePath);
const workingDir = join(tmpdir(), "thumbs");
const tmpFilePath = join(workingDir, "source.png");
if (fileName?.includes("#") || !object.contentType?.includes("image")) {
console.log("exists, returning false...");
return false;
}
// Ensure thumbnail dir exists
await fs.ensureDir(workingDir);
// Download source file
await bucket.file(filePath).download({
destination: tmpFilePath
});
// Resize the images and define an array of upload promises
const sizes = [64, 128, 320, 640];
const uploadPromises = sizes.map(async size => {
const imageName = fileName?.split(".")[0];
const imageExt = fileName?.split(".")[1];
const thumbName = `${imageName}#${size}.${imageExt}`;
const thumbPath = join(workingDir, thumbName);
// Resize source images
return sharp(tmpFilePath)
.resize(size, size)
.toFile(thumbPath)
.then(outputInfo => {
// Upload to GCS
return bucket
.upload(thumbPath, {
destination: join(bucketDir, thumbName)
})
.then(async res => {
return res[0]
.getSignedUrl({
action: "read",
expires: "01-01-2040"
})
.then(signedUrlRes => {
console.log(`url: ${signedUrlRes[0]}`);
// const docRef = db
// .collection("/cities")
// .doc(imageName?.split("_")[0] as string);
// return db.runTransaction(t => {
// t.set(docRef, {
// imageUrl: signedUrlRes[0]
// });
// return Promise.resolve();
// });
return db
.collection("/cities")
.doc(imageName?.split("_")[0] as string)
.set({
imageUrl: signedUrlRes[0]
})
.then(res => console.log("written"))
.catch(e => {
console.log("Firebase write error");
console.log(e);
throw Error(e);
});
})
.catch(e => {
console.log(e);
throw Error(e);
});
});
});
});
// Run upload operations
await Promise.all(uploadPromises).catch(e => {
console.log(e);
throw Error(e.message);
});
return fs.remove(workingDir).catch(e => {
console.log(e);
throw Error(e.message);
});
});
changed admin.initializeApp() from
admin.initializeApp({
credential: admin.credential.applicationDefault()
});
to
admin.initializeApp(functions.config().firebase);
I am working on a small project that works with generating pdf's in node and express, l am using the pdfkit npm module but to generate a pdf. l am also using the qr-image npm module to generate the QR code image but l am struggling to attach the generated the QR code to the pdf. This is the code that l am using to generate the QR code:
var file = "./"+certificationnumber+".png";
var qr_svg = qr.image(file, { type: 'png' });
qr_svg.pipe(require('fs').createWriteStream(file));
And this is how l am trying attache it to the pdf using pdfkit npm module:
doc.image(qr_svg.pipe(require('fs').createWriteStream(file)))
since every pdf has a unique QR code.
Thanks in advance
I exactly have the same problem where get the PDF in 64 bit encoded form and i have to attach qr image to it.
Below is the code snippet.
PDFDocument = require('pdfkit');
const base64 = require('base64-stream');
const doc = new PDFDocument();
doc.image('test.jpeg', {
fit: [250, 300],
align: 'center',
valign: 'center'
});
const finalString = pdf.response;
// contains the base64 string
//logic to append the qr image.
const stream = doc.pipe(base64.encode());
stream.on('data', chunk => finalString += chunk);
stream.on('end', () => {
// the stream is at its end, so push the resulting base64 string to the response
const backToPDF = new Buffer(finalString, 'base64');
read.writeFileSync('./Report.pdf', backToPDF);
});
doc.end();
Here is the solution I have come up with. Using pdf-lib, express and qrcode
const fs = require("fs");
const path = require("path");
const express = require("express");
const http = require("http");
const cors = require("cors");
const multer = require("multer");
const app = express();
const server = http.createServer(app);
const { PDFDocument } = require("pdf-lib");
const QRCode = require("qrcode");
const Joi = require("joi");
const { readFile, writeFile, unlink } = require("fs/promises");
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
const dir = "public";
const subDirectory = "public/uploads";
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir);
fs.mkdirSync(subDirectory);
}
const generateQRCodeImage = async function (filePath, text, color) {
return new Promise((resolve, reject) => {
QRCode.toFile(
filePath,
text,
{
color,
},
function (err) {
if (err) return reject(err);
resolve();
}
);
});
};
const run = async ({
width,
height,
x,
y,
pathToImage,
pathToPDF,
pathToOutputPDF,
qrCodeText,
qrDarkColor = "#000",
qrLightColor = "#0000",
}) => {
await generateQRCodeImage(pathToImage, qrCodeText, {
dark: qrDarkColor,
light: qrLightColor,
});
const pdfDoc = await PDFDocument.load(await readFile(pathToPDF));
const img = await pdfDoc.embedPng(await readFile(pathToImage));
Array.from({ length: pdfDoc.getPageCount() }).forEach((_, index) => {
let imagePage = pdfDoc.getPage(index);
imagePage.drawImage(img, {
x,
y,
width,
height,
});
});
const pdfBytes = await pdfDoc.save();
await writeFile(pathToOutputPDF, pdfBytes);
};
const pdfFileFilter = function (req, file, callback) {
const ext = path.extname(file.originalname);
if (ext !== ".pdf") {
return callback("This extension is not supported");
}
callback(null, true);
};
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, "public/uploads");
},
filename: function (req, file, cb) {
cb(
null,
file.fieldname + "-" + Date.now() + path.extname(file.originalname)
);
},
});
const filesToProcess = multer({ storage: storage, fileFilter: pdfFileFilter });
const schema = Joi.object({
width: Joi.string().regex(/^\d+$/).required(),
height: Joi.string().regex(/^\d+$/).required(),
x: Joi.string().regex(/^\d+$/).required(),
y: Joi.string().regex(/^\d+$/).required(),
qrCodeData: Joi.string().required(),
qrDarkColor: Joi.string(),
qrLightColor: Joi.string(),
});
app.post("/addQrToPdf", filesToProcess.array("file", 1), async (req, res) => {
const pathToImage = "public/uploads/" + Date.now() + "temp-qr.png";
const pathToOutputPDF = "public/uploads/" + Date.now() + "-output.pdf";
if (req.files) {
const [file] = req.files;
if (!file) {
res.send("No file detected on input");
}
const pathToPDF = file.path;
try {
const { width, height, x, y, qrCodeData, qrDarkColor, qrLightColor } =
await schema.validateAsync(req.body);
await run({
width: +width,
height: +height,
x: +x,
y: +y,
qrDarkColor,
qrLightColor,
qrCodeText: qrCodeData,
pathToImage,
pathToOutputPDF,
pathToPDF,
});
const pdfFile = await readFile(pathToOutputPDF);
res.contentType("application/pdf");
res.send(pdfFile);
await unlink(pathToImage);
await unlink(pathToPDF);
await unlink(pathToOutputPDF);
} catch (error) {
try {
await unlink(pathToPDF);
await unlink(pathToImage);
} catch (err) {
console.warn(err);
}
res.send(error);
}
}
});
server.listen(4000, () => console.log("listening on port *:4000"));
I had the same problem.
It looks like it is an async issue.
If you treat the generation of the QR code like a promise and then run the create pdf code, it works.
My code is below (using promise). It should also work using async await
const createPDF = (ticketID) => {
const doc = new pdf
doc.pipe(fs.createWriteStream(`${ticketID}.pdf`))
doc.text('Your Tickets').fontSize(25)
doc.image(`./qrCodes/${ticketID}.png`, {
fit: [250, 300],
align: 'center',
valign: 'center'
});
doc.end()
}
const createQRCode = (ticketID) => {
QR.toFile(`./qrCodes/${ticketID}.png`, String(ticket), {width: 250}).then(qr => {
createPDF(ticketID)
})
}
I use a version without writing to the disk, using the svg path output, extract the path from the qrcode data and render it into the pdf
let s = await toString('hallo2', {
type: 'svg'
})
// extract the 2nd path element
let path = Array.from(s.matchAll(/d="(.*?)"/gm))[1][1]
let doc = new PDFDocument({ size: 'A4' });
doc.scale(8)
.path(data)
.stroke()
doc.pipe(fs.createWriteStream('out2.pdf', {}));
doc.end()