How to download images from the database? - node.js

I need to upload files and images no larger than 2 megabytes in the database. But there is a problem downloading images. All images that are downloaded break and do not open. No such problems with text files.
Result of the downloaded image:
file 2.png
2.png: data
Uploading images this way:
module.exports.upload = async function (req, res) {
const sysFileObj = {
COMMENTS: req.body.COMMENTS,
NAME: req.file.originalname,
MIMETYPE: req.file.mimetype,
FILE_CONTENT: req.file.buffer
};
try {
await SysFiles.create(sysFileObj);
res.status(201).json(sysFileObj);
} catch (e) {
errorHandler(res, e);
}
};
multer:
const multer = require('multer');
const storage = multer.memoryStorage()
let obj = {
storage: storage,
limits: {
fileSize: 1024 * 1024 * 2
}
};
var upload = multer(obj)
module.exports = upload;
And here there is a problem when download:
module.exports.download = async function (req, res) {
try {
let sysFile = await SysFiles.findById(req.params.SYSFILE_ID);
var fileContents = Buffer.from(sysFile._props.FILE_CONTENT);
var readStream = new stream.PassThrough();
readStream.end(fileContents);
res.set('Content-disposition', 'attachment; filename=' + sysFile._props.NAME);
res.set('Content-Type', sysFile._props.MIMETYPE);
readStream.pipe(res);
} catch (e) {
errorHandler(res, e);
}
};
What am I doing wrong? Please tell me. I must say right away that I need to upload the image to the database without any links to any folder where the images will be stored.
Note:
But, by the way, when I downloaded the uploaded image using “SQL
Developer”, the image opens without any not problems.

You must store image content-Type
And image data
const formidable = require('formidable');
const _ = require('lodash');
const fs = require('fs');
// loading formidable library
let form = new formidable.IncomingForm();
// taking file extension
form.keepExtensions = true;
//processing for upload image
form.parse(request_data,(err,fields,files) => {
//if error when uploading image
if (err) {
return res.status(400).json({
err: 'Image could not bd uploaded'
})
}
// validating all fields without image
const {name, description, price, category, quantity, shipping} = fields;
if(!name || !description || !price || !category || !quantity || !shipping) {
return res.status(400).json({
err: 'All Fields are required'
})
}
// lets continue when there are no error
// form have available photo
if(files.photo){
//1 kb = 1000
//1 MB = 1000000
// check image size
if(files.photo.size > 2000000){
return res.status(400).json({
err: 'Image should be less than 2 MB'
})
}
// there are no error found then execute it
TAKING_AS_YOUR_VALRIABLE.data = fs.readFileSync(files.photo.path);
TAKING_AS_YOUR_VALRIABLE.contentType = files.photo.type
}
// finaly save product
//save it your own way
const FINAL_DATA = {...fields,...TAKING_AS_YOUR_VALRIABLE}
})
now show photo code
if(TAKING_AS_YOUR_VALRIABLE.data){
res.set('Content-Type',TAKING_AS_YOUR_VALRIABLE.contentType);
res.send(TAKING_AS_YOUR_VALRIABLE.data);
}

Related

Modify PDF file uploaded in the request body in nodejs

I'm trying to modify a pdf file that I get from the request then saving it in my server, I achieved to save it first as I received it from the request body and then modifying it, and once more saving it again with the modified version, but I was looking for another approach to modify it in the fly directly after receiving it from the request body then saving it only once in the server. I need to add a logo to the uploaded file, thanks in advance
This is my code
'''
const mongoose = require("mongoose");
const path = require("path");
const ErrorResponse = require("../utils/errorResponse");
const fs = require("fs");
// Form submition with photo
exports.uploadPdf = (req, folderPath, next) => {
if (!req.files) {
console.log("No file");
return next(new ErrorResponse("Please Upload a file", 400));
}
const file = req.files.pdf;
const extention = file.name.split(".").at(-1);
if (extention !== "pdf") {
console.log("It's not a valid PDF file");
return next(new ErrorResponse("Please Upload an pdf file", 400));
}
//Check image size
if (file.size > process.env.MAX_FILE_UPLOAD) {
return next(
new ErrorResponse(
`Please Upload an PDF file less than ${process.env.MAX_PDF_FILE_UPLOAD}`,
400
)
);
}
//Create custom filename
let id;
if (!req.params.id) {
id = mongoose.Types.ObjectId();
} else {
id = req.params.id;
}
file.name = `document_${id}${path.parse(file.name).ext}`;
var dir = `${process.env.FILE_UPLOAD_PATH}/${folderPath}`;
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true });
}
file.mv(
`${process.env.FILE_UPLOAD_PATH}/${folderPath}/${file.name}`,
async (err) => {
if (err) {
console.log(err);
return next(new ErrorResponse(`Problem with file upload`, 500));
}
}
);
req.body = {
_id: id,
...req.body,
pdf: file.name,
};
};
'''

Cloudinary uploader.upload executed after next async command in file

I'm trying to upload file with Multer and cloudinary node.js api and then remove temp file from hard drive, however file gets deleted before upload finished. Then I commented unlink files uploaded correctly
Here is my controller
const createGame = async (req, res) => {
const options = {
use_filename: true,
unique_filename: false,
overwrite: true,
};
try {
const data = req.body;
const files = req.files;
let posterPath = "";
let videoPath = "";
let distroPath = "";
if (files?.poster?.length) {
posterPath = files?.poster[0]?.path || "";
try {
const newPath = await uploader.upload(posterPath, options);
// Bug - unlink happens before file uploaded
await unlink(posterPath);
posterPath = newPath as string;
} catch (err) {
// Upload failure - remove files from disk
await unlink(posterPath);
posterPath = "";
}
}
if (files?.video?.length) {
videoPath = files?.video[0]?.path || "";
try {
const newPath = await uploader.upload(videoPath, {
...options,
resource_type: "video",
});
// Bug - unlink happens before file uploaded
await unlink(videoPath);
videoPath = newPath as string;
} catch (err) {
// Upload failure - remove files from disk
await unlink(videoPath);
videoPath = "";
}
}
const currentPublisher = await publishersRepository.findOneBy({
id: req.user.id,
});
if (!currentPublisher) {
res.status = 301;
return res.json({
message:
"You must be authenticated as publisher in order to add a game",
});
}
const newGameData = gamesRepository.create({
...data,
poster: posterPath,
video: videoPath,
distro: distroPath,
publisher: currentPublisher,
});
const newGame = await gamesRepository.save(newGameData);
res.status(200);
return res.json({ message: "Game added", data: newGame });
} catch (err) {
console.log("Error creating the game", err);
res.status(400);
return res.json({ message: "Error creating the game" });
}
};
I'm assuming you're using just one multer instance.
From what I looked at the docs of multer, the upload function is not a Promise. So the await function in front of uploader.upload method will not work.
What you need is to promisify your upload function. Here's an example:
const util = require('util');
// your code ...
try {
const promisifiedUploadFunc = util.promisify(uploader.upload);
const newPath = await promisifiedUploadFunc(posterPath, options);
// Bug - unlink happens before file uploaded
await unlink(posterPath);
posterPath = newPath as string;
} catch (e) {
// continue code..
}

Saving uploaded file to Pinata IPFS in NodeJS

I've been trying to save uploaded image files to IPFS in NodeJs , while it seems Pinata saves them, the files are pretty much gibberish (after downloading the images are broken).
My code :
// Nodejs route.
exports.postImage = async (req, res, next) => {
// Using multer to get the file.
fileUploadMiddleware(req, res, async (err) => {
// getting bunch of data from query string.
let meta = {
origin,
originid,
context,
ownerid,
format
} = req.query;
if(!meta.format || !req.files) {
return next(new ErrorResponse("File format not specified", 404));
}
if(!meta.originid) {
meta.originid = uuidv4();
}
// NOTE: is this the right way to get the data of the file ?
const buffer = req.files[0].buffer;
const filename = `${metadata.origin}_${metadata.originid}.${ metadata.format }`;
let stream;
try {
stream = Readable.from(buffer);
// HACK to make PINATA WORK.
stream.path = filename;
}
catch(e) {
logger.logError(e);
return false;
}
const options = {
pinataMetadata: {
name: filename,
keyvalues: {
context: metadata.context,
ownerid: metadata.ownerid
}
},
pinataOptions: {
cidVersion: 0
}
};
try {
var result = await pinata.pinFileToIPFS(stream, options);
console.log("SUCCESS ", result);
return result;
}
catch(e) {
logger.logError(e);
return null;
}
res.status(200).json({
success: true,
data: 'You got access'
})
});
}
So basically creating the stream based on the uploaded file buffer and sending it away to Pinata. Where do I go wrong?
const buffer = req.files[0].buffer;
If you used MemoryStorage. buffer property would be available. It is not available for diskStorage because it will save the file locally.:
const storage = multer.memoryStorage()
const upload = multer({ storage: storage })
Also I think it not req.files[0]
const buffer = req.file.buffer;
after I get the buffer, I convert it to FormData using form-data npm package:
import FormData from "form-data";
const formData = new FormData();
formData.append("file", buffer, {
contentType,
filename: fileName + "-" + uuidv4(),
});
then you send a post request to pinata
const url = `https://api.pinata.cloud/pinning/pinFileToIPFS`;
const fileRes = await axios.post(url, formData, {
maxBodyLength: Infinity,
headers: {
// formData.getBoundary() is specific to npm package. native javascript FormData does not have this method
"Content-Type": `multipart/form-data: boundary=${formData.getBoundary()}`,
pinata_api_key: pinataApiKey,
pinata_secret_api_key: pinataSecretApiKey,
},
});

application/octet-stream issue while using google moderate images trigger (blur image)

I,m using moderate images solution trigger from google.
I taked this solution from here.
I ask some to upgrade for me this solution & here is code:
'use strict'
const gm = require('gm').subClass({imageMagick: true})
const functions = require('firebase-functions')
const admin = require('firebase-admin')
admin.initializeApp()
const Vision = require('#google-cloud/vision')
const vision = new Vision.ImageAnnotatorClient()
const spawn = require('child-process-promise').spawn
const path = require('path')
const fs = require('fs')
const { Storage } = require('#google-cloud/storage')
const gcs = new Storage({
projectId: xxxxxxxxxxx,
})
exports.blurOffensiveImages = functions.storage
.object()
.onFinalize(async (object) => {
const file = gcs.bucket(object.bucket).file(object.name)
const filePath = `gs://${object.bucket}/${object.name}`
console.log(`Analyzing ${file.name}.`)
try {
const [result] = await vision.safeSearchDetection(filePath)
const detections = result.safeSearchAnnotation || {}
if (
detections.adult === 'VERY_LIKELY' ||
detections.violence === 'VERY_LIKELY'
) {
console.log(`Detected ${file.name} as inappropriate.`)
await blurImage(file, object.bucket, object.metadata)
console.log('Deleted local file', file)
return null
} else {
console.log(`Detected ${file.name} as OK.`)
}
} catch (err) {
console.error(`Failed to analyze ${file.name}.`, err)
throw err
}
})
async function blurImage(file, bucketName, metadata) {
const tempLocalPath = `/tmp/${path.parse(file.name).base}`
const bucket = gcs.bucket(bucketName)
await file.download({ destination: tempLocalPath })
console.log('The file has been downloaded to', tempLocalPath)
// Blur the image using ImageMagick.
await new Promise((resolve, reject) => {
gm(tempLocalPath)
.blur(0, 20)
.write(tempLocalPath, (err, stdout) => {
if (err) {
console.error('Failed to blur image.', err);
reject(err);
} else {
console.log(`Blurred image: ${file.name}`);
resolve(stdout);
}
});
});
console.log('Blurred image created at', tempLocalPath)
await bucket.upload(tempLocalPath, {
destination: file.name,
metadata: { metadata: metadata },
})
console.log('Blurred image uploaded to Storage at', file)
return fs.unlink(tempLocalPath, (e) => { if (e) {console.log(e)}})
}
End it's worked perfect, with one bad issue.
Sometimes when user sending list of photos i have "application/octet-stream" file type, but it should be "image/jpg" all media files at my project should be image/jpg.
one user's publication with error in image data type
It's looks like this trigger stuck when it executing.
I made delay in uploading images in my project, but it's doesn't helps me.
I tested - when i delete this trigger - all uploading photos is well & no issues at all.
Help me fix it.
P.S. want to say also, after uploading - image should have all data like original. (Destination, name etc.)

how to upload a image file in node.js?

var title="this is title";
var content="this is content";
const config = { headers: {'Accept': 'application/json', 'Content-Type': 'multipart/form-data' } };
const form = new FormData()
let file =event.target.files[0]
form.append('file', file)
form.append('title', title)
form.append('content', content)`enter code here`
Axios.post("http://localhost:3001/article/get/123", form,config ).then((res)=>{
console.log(res.data)
})
in node I have used multer for upload image or anything.
Below is the code for upload which I have used as a middleware.
const util = require("util");
const path = require("path");
const multer = require("multer");
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, "./Uploads") // folder path where to upload
},
filename: function (req, file, cb) {
cb(null, file.originalname + "-" + Date.now() + path.extname(file.originalname))
}
});
const maxSize = 1 * 20000 * 20000; // file size validation
const uploadFiles = multer({ storage: storage, limits: { fileSize: maxSize } }).array("myfiles", 10); // key name should be myfiles in postman while upload
const uploadFilesMiddleware = util.promisify(uploadFiles);
module.exports = uploadFilesMiddleware;
Below is the function which I have created in controller for upload and file check.
fileUpload = async (req, res) => {
try {
let userCode = req.headers.user_code;
await upload(req, res);
if (req.files.length <= 0) {
return res.status(httpStatusCode.OK).send(responseGenerators({}, httpStatusCode.OK, 'Kindly select a file to upload..!!', true));
}
let response = [];
for (const element of req.files) {
let data = await service.addFileData(element, userCode);
response.push(data); // for file path to be stored in database
}
if (response && response.length > 0) {
return res.status(httpStatusCode.OK).send(responseGenerators(response, httpStatusCode.OK, 'File uploaded sucessfully..!!', false));
} else {
return res.status(httpStatusCode.OK).send(responseGenerators({}, httpStatusCode.OK, 'Failed to upload file kindly try later..!!', true));
}
} catch (error) {
logger.warn(`Error while fetch post data. Error: %j %s`, error, error)
return res.status(httpStatusCode.INTERNAL_SERVER_ERROR).send(responseGenerators({}, httpStatusCode.INTERNAL_SERVER_ERROR, 'Error while uploading file data', true))
}
}
and the route will go like this.
router.post('/upload/file', fileUploadController.fileUpload);
And be sure to keep same name in postman while file upload as in middleware.
The above code is in react.js. I want to do same work in node.js and the file will be upload from the public folder. main issue is how to upload image file in format like we have in frontend event.target.files[0]

Resources