Converting blob from database to an image javascript - node.js

I have a database, where one of the tables has a blob field and I want to display it as an image. I can't really find any solution for this - any working npm package or a sample of code would be useful. I'm using reactjs and nodejs.

What you want to do is create an URL that you can pass to the img src of the HTML img
JS
var url = window.URL || window.webkitURL;
var imageSrc = url.createObjectURL('your blob');
document.querySelector("#myimage").src = imageSrc;
HTML
<img id="myimage"/>

Method 1 create readable stream and pipe to response
var stream = require('stream');
var bufferStream = new stream.PassThrough();
bufferStream.end(new Buffer( blob, 'binary' ));
res.writeHead(200, {
'Content-Type' : 'image/jpg'
});
// res is standered express res object
bufferStream.pipe(res)
Method 2
pass blob to base64
var bufferBase64 = new Buffer( blob, 'binary' ).toString('base64');
show image
class Example extends React.Component{
render() {
return <img src={"data:image/jpeg;" + bufferBase64} />
}
}
reference
https://stackoverflow.com/.../how-to-create-a-readstream-with-a-buffer-using-nodejs

Related

Create a Blob for Video in NodeJs18 and Use it on Client Side

Learning NodeJs and Blob, and I Try to Create a Blob from a Video File in NodeJS. And send this in a Json file to my Client. Data will be Fetch inside GetStaticProps in NextJS.
Here is What I Created in NodeJS Server :
const fileBuffer = fs.readFileSync(filePath); // Path is something like example.com/video.mp4
const blob = new Blob([fileBuffer], { type: 'video/mp4' });
blobUrl = URL.createObjectURL(blob); // Return blob:nodedata:c3b1baf2-fba8-404f-8d3c-a1184a3a6db2
It retrun this :
blob:nodedata:c3b1baf2-fba8-404f-8d3c-a1184a3a6db2
But How can I use it in Client ? <video src="blob:nodedat..." is not Working, so I am doing something wrong for sure
Can you help me uderstand what is wrong ?

Serve clickable download URL in NodeJS

At my endpoint in my NodeJS server, after retrieving an audio file stored as a Buffer in MongoDB, I want to represent it with a URL (much like how you do with URL.createObjectURL(blob) in the frontend on the browser). I then plan to res.render() the URL in HTML through Handlebars on the client, so that the user can click on it to download it:
<a href={{url}}>Click me to download the file!</a>
In the NodeJs server, I have converted the MongoDB Buffer into a JavaScript ArrayBuffer through:
var buffer = Buffer.from(recordingFiles[0].blobFile);
var arrayBuffer = Uint8Array.from(buffer).buffer;
I am unsure where to proceed from here. I seen solutions using fs or res.download(), but they don't seem applicable to my situation. Thanks in advance for any help!
Hopefully this can help.
var blob = new Blob(BUFFER, {type: "audio mime type"});
var link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
var fileName = reportName;
link.download = fileName;
link.click();
Do you always need to preload the audio file onto the page?
If not, then I would advise you to add a separate endpoint to download the file on demand. The frontend link can send a get request to the endpoint and download the file only if the user clicked it.
Otherwise you'd always be downloading the buffer behind the scenes, even if the user didn't intend to download it. This is especially problematic on slow connections.
Frontend:
<a href={{`${baseUrl}/download/${audioId}`}}>Click me to download the file!</a>
Backend:
const stream = require('stream');
app.get('/download/:audioId', function (request, response) {
// Retrieve the tag from our URL path
const audioId = request.params.audioId;
const fileData; // TODO: Get file buffer from mongo.
const fileContents = Buffer.from(fileData, 'base64');
const readStream = new stream.PassThrough();
readStream.end(fileContents);
response.set('Content-disposition', 'attachment; filename=' + fileName);
response.set('Content-Type', '<your MIME type here>');
readStream.pipe(response);
});
A list of relevant MIME types can be found here.

Download image from Express (Back-end) using React (Front-end)

I have an image stored in Express server. I have been trying to download the image using the following method in a React component.
<a href={my_image_url_from_state} download>Download Image</a>
But when i click on the 'Download Image' image is not downloaded. I see this error message:
I am able to display the same image in img tag, ie
<img src={my_image_url_from_state} />
that means nothing wrong with URL.
Do I need to make any changes in Express to download any files?
You need to write a function and invoke it on OnClick of the download button.
<button onClick={() => {download()}}>Download</button>
download function would be:
function download() {
var link = document.createElement('a');
link.href = 'images.jpg';
link.download = '<The URL of the image>';
document.body.appendChild(link);
link.click();
}
working code in reactJS class
class App extends React.Component {
constructor() {
super();
}
render() {
return (
<div>
<img onClick={() => { download(); }} src="<The URL of the image>" />
</div>
);
}
}
function download() {
var link = document.createElement('a');
link.href = 'images.jpg';
link.download = '<The URL of the image>';
document.body.appendChild(link);
link.click();
}
I ended up here because I was looking for a way to download an image in my React app from cloudinary and I found the snippet above as a useful starting point. I was getting the same error as Darshn. I speculate that perhaps the reason it wasn't working is that the backend origin url was different than the client app's origin.
I then researched and found that the download attribute of an anchor element only works for same-origin URLs. See The Anchor element
I then found an article on Soumitra Roy Sarkar's Roy Tutorials that I was able to incorporate into a solution.
I determined that since I was pulling from a different origin I would need to fetch the image, convert it to a Blob, create a URL for it, attach the url to the anchor tag.
Since I already was using the Cloudinary React SDK I was able to add the cloudinary-core to my dependencies.
yarn add cloudinary-core
Then I imported it into my module
import cloudinary from 'cloudinary-core';
const cloudinaryCore = new cloudinary.Cloudinary({cloud_name: '<My Cloudinary Cloud Name>'});
My download function looks like:
function download({publicKey, name}) {
const downloadUrl = `${cloudinaryCore.url(publicKey)}.jpg`;
fetch(downloadUrl)
.then((img) => img.blob())
.then((blob) => {
let url = window.URL.createObjectURL(blob);
let link = document.createElement('a');
link.href = url;
link.download = name;
link.click();
})
}
The function can be called by an html element like this:
<button onClick={() => {download({publicKey: '12345', name: 'image.jpg'})}}>Download</button>

Node.js pipe image into memory and display it

I am making a Node.js/Electron application that downloads and displays images. I am downloading an image from the internet using request. I want to save this image in memory and display it without saving the file on the local hard drive. I am aware I could accomplish what I am asking here by inserting <img src="url"> into the DOM, but this is a heavily simplified version of my code and what I am trying to accomplish can not be done with that.
var image = fs.createWriteStream(?); // Is there anyway to save the image to memory?
request(url).pipe(image);
$('img').exampleScriptToSetImage(image); // And is there any way to display that image in a element without saving it to the local disk and loading its path?
Indeed! You can pipe your requested image data into a concat stream, convert the buffer to base64, and set the base64 encoding as your image source.
var path = require('path')
var request = require('request') // or hyperquest, simple-get, etc...
var concat = require('concat-stream')
var image = request(url)
image.pipe(concat({ encoding: 'buffer' }, function (buf) {
var ext = path.extname(file.name).slice(1) // assuming you have the file name
if (ext === 'svg') ext = 'svg+xml'
var src = 'data:image/' + ext + ';base64,' + buf.toString('base64')
var img = document.createElement('img')
img.src = src
document.body.appendChild(img)
})

How to gzip http request post(client) data for node.js server

I have implemented node.js server application, which accepts post data from client(long json string). Is there a way I can gzip the post data at browser end and unzip it in node.js?
I specifically want to gzip the request and not response.
check https://jsfiddle.net/gynz82tg/
decompress in nodejs just same after you get the base64 encoded request string.
var jsonStr = JSON.stringify({
name: "JiangYD"
})
$('#origin').text(jsonStr);
var zip = new JSZip();
zip.file("data", jsonStr);
var content = zip.generate();
$('#compressed').text(content);
zip = new JSZip(content, {base64:true});
$('#decompressed').text(zip.file("data").asText());
<script src="https://raw.githubusercontent.com/Stuk/jszip/master/dist/jszip.js"></script>
<div id='origin'></div>
<div id='compressed'></div>
<div id='decompressed'></div>
UPDATE
because jsZip update the API
https://jsfiddle.net/cvuqr6h4/
async function go(){
const jsonStr = JSON.stringify({
name: "JiangYD"
})
$('#origin').text(jsonStr);
let zip = new JSZip();
zip.file("data", jsonStr);
const content = await zip.generateAsync({type : "base64"});
$('#compressed').text(content);
zip = new JSZip();
await zip.loadAsync(content, {base64:true});
const decoded = await zip.file("data").async('string');
$('#decompressed').text(decoded);
}
go();
You could try this: https://github.com/sapienlab/jsonpack
Example Client Code:
<script src="jsonpack.js" />
<script>
var BIG_JSON = {.....};
var packed = jsonpack.pack(BIG_JSON);
$.post('path_to_server',packed);
</script>
Example Nodejs Code:
var jsonpack = require('jsonpack/main');
app.on('/packed_data',function(req,res){
try{
jsonpack.unpack(req.data);
}catch(e){
//not good packed data.
}
})
This is a sample code of course i don't know what framework or libraries you use, but you can see how this could be implemented.
Anyway be careful with this because zipping and unzipping data is always a heavy cpu bound task. If you have several megabytes of data you dont want to make your users from phones,tablets etc.. to make this tasks!

Resources