Nodejs convert image to byte array - node.js

That I would like to convert into a byte array.
I get the file with <v-file-input> and this is the input of it.
I would like to convert it on the client side, then send it to the backend to be uploaded to the sql server.
I've tried to search it on google for hours.

Try to add this file object to FormData and send it to nodejs. On a server side you can use multer to decode multipart formdata to req.file for instance
on a client side:
const formData = new FormData()
formData.append('file', file)
const { data: result } = await axios.post(`/api/upload-image`, formData)
on a server side:
const multer = require('multer')
const upload = multer()
...
router.post('/upload-image', upload.single('file'), uploadImageFile)
...
uploadImageFile(req, res) {
// multer writes decoded file content to req.file
const byteContent = req.file
res.end()
}

Related

Express, Multer, and Cloudinary not returning full cloudinary response

I'm using Multer/multer-storage-cloudinary to upload images directly to Cloudinary rather first uploading it to a local temp directory, then sending it to Cloudinary:
const express = require('express');
const router = express.Router({mergeParams:true});
if (app.get('env') == 'development'){ require('dotenv').config(); }
const crypto = require('crypto');
const cloudinary = require('cloudinary').v2;
const { CloudinaryStorage } = require('multer-storage-cloudinary');
const multer = require('multer');
const { storage } = require('../cloudinary');
const upload = multer({storage});
//configure cloudinary upload settings
cloudinary.config({
cloud_name:process.env.CLOUDINARY_NAME,
api_key: process.env.CLOUDINARY_API_KEY,
api_secret: process.env.CLOUDINARY_API_SECRET
});
const storage = new CloudinaryStorage({
cloudinary: cloudinary,
folder: ('book_tracker/'+process.env.CLOUDINARY_FOLDER+'posts'),
allowedFormats: ['jpeg', 'jpg', 'png'],
filename: function (req, file, cb) {
let buf = crypto.randomBytes(16);
buf = buf.toString('hex');
let uniqFileName = file.originalname.replace(/\.jpeg|\.jpg|\.png/ig, '');
uniqFileName += buf;
console.log(req.body);
cb(undefined, uniqFileName );
}
});
const middleware = {
function asyncErrorHandler: (fn) =>
(req, res, next) => {
Promise.resolve(fn(req, res, next))
.catch(next);
}
}
/* POST create user page */
router.post('/register', upload.single('image'), asyncErrorHandler(postRegister));
What I'm running into is that the response I'm getting in req.file is not the full Cloudinary response which includes public_id, etc. Instead it's like this:
{
fieldname: 'image',
originalname: 'My Headshot.jpg',
encoding: '7bit',
mimetype: 'image/jpeg',
path: 'https://res.cloudinary.com/<cloudinary_name>/image/upload/v1611267647/<public_id>.jpg',
size: 379632,
filename: '<public_id>'
}
It's been a while since I worked with multer-storage-cloudinary, though that storage was taken directly from an old project that would return the correct information. Is there something in multer, or multer-storage-cloudinary, that I need to set in order to put the full cloudinary response into req.file?
The multer-storage-cloudinary package is a third party package that integrates multer and Cloudinary in a streamlined way, but it doesn't expose all possible options or responses from the Cloudinary SDK or API
In your example, it's not returning the full API response from Cloudinary, but a subset of the fields, because the file object's filename, path, and size properties are taken from the Cloudinary API response (from the public_id, secure_url, and bytes properties of the API response respectively), but the other fields aren't mapped: https://github.com/affanshahid/multer-storage-cloudinary#file-properties
If you need the full set of response values (or some specific values not mapped already) you can:
Ask the package maintainer to add support for other fields
Fork the package and map additional fields yourself; the fields are mapped here though I'm not sure what else may need to be changed: https://github.com/affanshahid/multer-storage-cloudinary/blob/1eb903d44ac6dd42eb1ab655b1e108acd97ed4ca/src/index.ts#L83-L86
Switch from using that package for wrapping the Cloudinary SDK to use the Cloudinary SDK directly in your own code, so you can handle the response directly.
Leave it as it is now and make a separate call to the Cloudinary Admin API to fetch the other details of the image(s): https://cloudinary.com/documentation/admin_api#get_resources
Leave it as-is, but add a notification_url so that as well as the API call response, the details of the new upload will be sent in an HTTP POST request to a URL of your choice: https://cloudinary.com/documentation/notifications
The notification_url can be specified in the Upload API call, Upload Preset, or at the account-level in the Cloudinary account settings.

How to send in Angular http post request with data + image?

In a post request (in Angular), I usually send data (for example like 'product' data) using an 'object':
product: any = {}; // filled of proprieties (code, barcode, name, description...)
and then pass this in the request:
return this.http
.post<any>( Url , product)
.pipe(catchError(this.errorHandler));
using ExpressJS I can easly retrieve the proprieties 'req.body.<< propriety >>' :
router.post("/newProduct", function (req, res, next) {
const code = req.body.code;
const barcode = req.body.barcode;
const nameProduct = req.body.name;
const description = req.body.description;
//.. here other code - mySql to insert data in the DB ..
});
THE PROBLEM
Now I would like to send the same data (like in the example) and also an image to save on the server.
PS
I tried to use FormData:
var formData = new FormData();
formData.append('image', imageFile);
formData.append('product', product);
return this.http
.post<any>(this.newProductUrl, formData )
.pipe(catchError(this.errorHandler));
So in the backend, I can retrieve and save the image using the npm package 'multer' but then I don't know how to get the 'product' data.
You can access your image data added in formData with 'request.file' and your others data will be available on 'request.body'
To Upload the image in backend multer.upload('image') will be used. Here image is the key that you have in your formdata.
// frontend
var formData = new FormData();
formData.append('image', imageFile);
formData.append('product', product);
// backend
var upload = multer({ dest: 'uploads/' }) // uploads your destination folder
app.post('/profile', upload.single('image'), function (req, res, next) {
// req.file is the `image` file
// req.body will hold the text fields, if there were any
});

How to upload file from nodeJS to nodeJS

I have 2 nodeJS services and I would want to upload file in a dir, from one NodeJS (backend) to another NodeJS(backend). The receiver nodeJS is an express app.
Looking for some working code sample.
PS: Couldn't find any code samples in search, since everywhere it was Multer from client to server uploads that receives multipart/form-data.
Uploading file using POST request in Node.js
Receive the file first as you correctly said using Multer. Then, you may either save the file to a temporary directory before uploading it again or just send the file as-is.
You need to setup a server running with Multer on the 2nd server that wishes to receive the file.
const express = require('express');
const app = express();
const upload = multer({ dest: 'files/' });
app.post('/upload', upload.single('file'), (req, res) => {
res.sendStatus(200);
});
app.listen(3001);
Then on the server you wish to send the file from, do something like this:
const request = require('request');
const req = request.post('localhost:3001/upload', (err, res, body) => {
if (err) throw new Error(err);
if (res && res.statusCode == 200) {
console.log('Success');
} else {
console.log('Error');
};
});
const form = req.form();
form.append('file', fs.createReadStream('./location/to/file'));

I got the error while uploading image in mongodb Cannot read property 'buffer' of undefined

When I upload the pdf using multer in mongodb in node js then I got error "Cannot read property 'buffer' of undefined".I am trying to upload the pdf file in database.Please help to resolve this issue.Thanks in advance.
const express=require('express');
const multer=require('multer');
const getstream = require('get-stream');
const resume=require('../model/Resume')
const router = new express.Router();
const uplaod = multer({
limits:{
fileSize: 100000
},
fileFilter(req,file,cb)
{
if(!file.originalname.endsWith('pdf'))
{
return cb(new Error('Upload the pdf file'))
}
cb(undefined,true);
}
});
router.post('/Resume',uplaod.single('avatar'),async (req,res)=>{
req.resume.avatar=req.file.buffer
await req.resume.save();
res.send({sucess:'sucess'});
},(error,req,res,next)=>{
//It is used for print message otherwise it will give long html message
res.status(404).send({error:error.message});
})
module.exports=router;
req.file does not exist, that's why you got this error
I think it should be req.files.file.buffer
if not, try to console.log(req), and trace it to find the file
if there is no files or file in the req object, then the file hasn't been sent to the request

Creating ReadStream From Uploaded File on Node.js

I am trying to receive a file on Node.js Express framework (via express-fileupload middleware), and then POST it directly to another server via the request package without saving it on the first device's disk and then re-reading it.
const streamifier = require('streamifier');
const fileUpload = require('express-fileupload');
app.use(fileUpload());
app.post('/upload', function(req, res) {
var fileBuffer = req.files.upload.data;
var fileReadStream = streamifier.createReadStream(fileBuffer);
//Use 'request' to send fileReadStream to another API for additional processing
}
However, the receiving API does not receive any file when I run this code.
When I run this other code, however, it works fine, but fs is only able to create a ReadStream from a file on the server, so it would involve me saving the file to some temporary hard disk location first, reading it again, and then sending it to the remote API, which I think is a bit wasteful.
var fs = require('fs');
app.post('/upload', function(req, res) {
var fileReadStream = fs.createReadStream('test.txt');
//Use 'request' to send fileReadStream to another API for additional processing
}
Any idea why the 1st code block results in no file received by the external API, while the 2nd one works perfectly fine? It seems that fileReadStream would be the same in both cases.
Turns out I should have just been sending the buffer by itself without transforming it into a ReadStream. However, I did have to add the name to it, or the receiving API wouldn't recognize that I was sending a file.
const fileUpload = require('express-fileupload');
app.use(fileUpload());
app.post('/upload', function(req, res) {
var fileBuffer = req.files.upload.data;
fileBuffer.name = 'test.png';
//Use 'request' to send fileBuffer to another API for additional processing
}

Resources