Blob url doesn't exsists? - javascript

Blob link is created, but the link returns 404 error
About this code; I am making markdown text editor, and am working on copy/paste image functionality, such as from screenshot. When paste action is made, this code should console.log blob url of a pasted image. But it looks like image doesn't exsists when I go to blob link.
What I did wrong for passing the image as blob?
code
import { useState } from 'react'
import { ReactMarkdown } from 'react-markdown/lib/react-markdown'
export default function Home() {
const [input, setInput] = useState('')
const handlePaste = async(e) => {
var items = e.clipboardData.items;
let image = [].slice.call(items).filter((obj)=> {
// Filter the image items only
return obj.type.indexOf('image') !== -1;
})
const item = image[0];
console.log(item)
// Get the blob of image
const blob = await item.getAsFile();
let blobURL = URL.createObjectURL(blob);
console.log(blobURL)
};
return (
<>
<textarea
name=""
id=""
cols="30"
rows="10"
value={input}
onPaste={handlePaste}
onChange={(e)=>setInput(e.target.value)}
/>
<ReactMarkdown childrenhow ={input}/>
</>
)
}

You can't "go to the link". You can access the blob as a File object, and you can use the object URL as e.g. the src attribute of an img tag within the same document. But the object URL stops referring to anything as soon as you leave the page.

Related

How can I "fake" a url to an html page from an html string?

On my React website, I'd like to generate an image from an html string.
I've found html-to-image which seems stable and popular, but it requires a URL to the page of which I want to take a screenshot of.
How can I generate a "fake" URL to give it?
The HTML string I have is basically a design of the image I want but the content depends on user input.
EDIT: (added the HTML string)
This is my HTML string:
<!DOCTYPE html> <html> <body> <div style="width:500px;margin:0px;padding:0px;background-color:white' \
';"><div> <div style="padding:50px"> <p ' \
'style="color:#9F9F9F;font-size:13px;font-family:verdana;margin-top:0px">VARIABLEVARIABLE</p> <p ' \
'style="color:#3F3F3F;font-size:26px;font-weight:900;margin-top:0px;margin-bottom:18px;font-family' \
':verdana">VARIABLEVARIABLE</p> <p style="color:#3F3F3F;font-size:15px;font-weight:500;margin-top:0px;font-family' \
':verdana">VARIABLEVARIABLE</p> </div> <div style="width:100%;height:10px;background-color:#EFF5F8;"></div><div ' \
'style="padding:50px"> <p style="color:#9F9F9F;font-size:13px;font-family:verdana">VARIABLEVARIABLE</p> <p ' \
'style="color:#3F3F3F;font-size:15px;font-weight:500;margin-top:0px;font-family:verdana">VARIABLEVARIABLE</p> ' \
'</div></div> <div style="width:100%;height:55px;background-color:#313131;margin-right:0px;margin-left' \
':0px;line-height:55px;"> <p style="color:#ffffff;font-size:15px;font-weight:500;font-family:verdana' \
';margin-left:50px">VARIABLEVARIABLE</p> </div> </div> </body> </html>
So I get data fom the server, then replace where I wrote VARIABLEVARIABLE with some of the data and I want to present it to the user as an image.
EDIT 2 :
Reading the comment from #programoholic I think that he's right and I got it wrong. I kept seeing dataUrl but I understand now that it's not an actual URL that needs to be passed, but just a reference to the node in which the HTML exists.
I'm still unsure how to approach this, but it does change the question.
I'll try to set the html to the node once I get the data and then take a snap of that, maybe that'll work.
html-to-string doesn't require any url. Instead you can use the useRef to select the node and then generate the html content as an image like below :
import React, { useRef, useCallback } from 'react';
import './style.css';
import { toPng } from 'html-to-image';
export default function App() {
const ref = useRef();
const onButtonClick = useCallback(() => {
if (ref.current === null) {
return;
}
toPng(ref.current, { cacheBust: true })
.then((dataUrl) => {
const link = document.createElement('a');
link.download = 'my-image-name.png';
link.href = dataUrl;
link.click();
})
.catch((err) => {
console.log(err);
});
}, [ref]);
return (
<div ref={ref}>
<h1>Hello StackBlitz!</h1>
<p>Start editing to see some magic happen :) p</p>
<button onClick={onButtonClick}> download png </button>
</div>
);
}
Here is the. : Stackblitz
html-to-image wants base64 url , so you can create image to base64 with javascript code.
const base64Convertor = (file) => {
return new Promise((resolve, reject) => {
const fileReader = new FileReader();
fileReader.readAsDataURL(file);
fileReader.onload = () => {
resolve(fileReader.result);
};
fileReader.onerror = (error) => {
reject(error);
};
});
};
You can add some JavaScript to replace the contents of some HTML elements with the value of your variable, which can be taken from a URL parameter.
Then pass the URL with the value in the parameter.
Eg: /generate-image.html?variable=Hello
// Get variable from URL query params
const urlSearchParams = new URLSearchParams(window.location.search);
const variable = urlSearchParams.get('variable') || 'default value';
// Update all HTML elements with data-variable
const elements = document.querySelectorAll('[data-variable]');
for (element of elements) {
element.textContent = variable;
}
<h1 data-variable="true"></h1>
<p data-variable="true"></p>

Any function to Download rendered images from Fetched Api in javascript

I tried to get random images from unsplash api by given code below, now i am looking for to way to DOWNLOAD displayed image from that Api
const numItemsToGenerate = 1;
function renderItem(){
fetch(`https://source.unsplash.com/920x720?
beach`).then((response)=> {
let item = document.getElementById('container');
item.innerHTML = `
<img class="beach_image" src="${response.url}"
alt="beach image"/>
`
})
}
for(let i=0;i<numItemsToGenerate;i++){
renderItem();
}
I have created a function, that downloads the image from the unsplash. But the problem is, it doesn't work on Stackoverflow's snippet, since is creates null blob URL. You need to run this program on a server (like localhost), in order to work.
Try it on - https://jsfiddle.net/xt5wb2vn/
HTML
<div id="container">
</div>
<button class="download">Click to download</button>
JavaScript
const numItemsToGenerate = 1;
function downloadImage(url) {
let a = document.createElement("a");
a.href = url;
a.download = 'image.jpg';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}
function renderItem() {
fetch(`https://source.unsplash.com/920x720?beach`)
.then(resp => resp.blob())
.then(image => {
const image_url = URL.createObjectURL(image)
let item = document.getElementById('container');
item.innerHTML = `<img class="beach_image" src="${image_url}" alt="beach image"/>`;
return image_url;
}).then(url=>document.querySelector(".download").onclick = ()=>downloadImage(url))
}
renderItem()
Use URL.createObjectURL
So, the function should look like
fetch(`https://source.unsplash.com/920x720?beach`)
.then(resp => resp.blob())
.then(image => {
const image_url = URL.createObjectURL(image)
const item = document.getElementById('container')
item.src = image_url
})

Display img receive from API as Stream

How can I read a stream from the api to display it in the src of an img tag ?
With this response I just want to display it in a <img src="myStream" />
My first error was to try to display a pdf file in an <img/> tag. I used an <iframe /> instead.
Also I had to use fetch to make the request and after use response.blob() :
const myFunctionToConvertHttpResponseToFileUrl = () => async {
const response = await fetch('myurl.com')
const myBlob = response.blob()
this.fileURL = URL.createObjectURL(myBlob);
}
And After in the html
<iframe :src="fileUrl" type="application/pdf" />

Is it possible to display an image that has been selected by an input element?

I wish to display an input element's selected image. Can this be performed on a local file, accessing the image client side, or would I need to upload the image to a server?
Here's my attempt in React. I can access the correct file name from the input element using inputElem.files[0].name. As soon as I am trying to set an image element to it, the broken image icon is displayed, and no error is surfaced.
const App = () => {
// state to keep track of img elements src. The default works fine.
const [imgSrc, setImgSrc] = useState('/images/test.jpg')
function handleImgUpload() {
const url = '/images/' + e.target.files[0].name
setImgSrc(url)
console.log(url) // /images/26e3e793-98f5-4720-9f82-8963276d5e27.JPG
}
function handleImgLoadSuccess() {
console.log('image loaded!')
}
function handleImgLoadError() {
console.log('image not loaded')
}
return (
<div>
<div>
<label htmlFor="img">Select an image:</label>
<input
type="file"
id="img"
name="img"
accept="image/png, image/jpeg"
onChange={(e) => handleImgUpload(e)}
/>
</div>
<img
src={imgSrc}
alt="Your upload"
onLoad={handleImgLoadSuccess}
onError={handleImgLoadError}
/>
</div>
)
}
In the console, however, the url seems to be correct.
<img src="/images/26e3e793-98f5-4720-9f82-8963276d5e27.JPG" height="100" width="200" alt="Input" class="jsx-855240488">
Hey – I see what you're trying to do, but it doesn't look like this will work. You need to create a new file reader.
const showTempImage = (e) => {
const file = e.target.files[0];
const img = document.createElement("img");
const reader = new FileReader();
reader.addEventListener('load', (e) => {
img.src = e.target.result;
});
reader.readAsDataURL(file);
// Append the img tag to the dom somewhere
}
This did the trick by creating a correct blob url.
const inputImg = e.target.files[0]
const url = URL.createObjectURL(inputImg)
// blob:http://localhost:3000/test-img.jpg
The resulting file stays in memory and needs to be removed in order to create memory leaks.
URL.revokeObjectURL(url)
This also seems to be accomplishable with FileReader, though there are differences.

How to make attachment downloadable - Angular

I have a scenario where user can upload files (PDF/PNG) and show if any files are already uploaded. I'm able to do Uploading part and showing the user any files are already uploaded. Now I want the user can download if any uploaded files are present on clicking on the attachment. Could you guys advise?
ts file
upload() {
const fileUpload = this.fileUpload.nativeElement; //* retrieve native DOM element wrapped by ElementRef
fileUpload.onchange = () => {
const file = fileUpload.files[0]; // retrieve file
if (file) {
const filesize = getFileSizeHelper(file.size); // get file size
if (filesize <= 2) {
this.filename = file.name;
this.uploadFile(file);
} else {
this.fileSizeEr.emit(true);
}
}
};
fileUpload.click(); // open file picker window
}
/**
* method to upload file
*/
uploadFile(file: any) {
const formData = new FormData();
formData.append('file', file, file.name);
this.myservice.uploadFile(formData).subscribe((res: any) => {
this.uploadedFile = res;
this.fileUploadRes.emit(res); //emit response object to parent component
});
}
HTML file
<div class="upload-space" (click)="upload()">
<mat-icon *ngIf="!doc?.fileName">publish</mat-icon>
<span *ngIf="!doc?.fileName">
{{ "PNG and PDF files allowed(max.2MB)" | translate }}
</span>
<span *ngIf="doc?.fileName">
{{ doc.fileName }}
</span>
<!-- <span *ngIf="filename">
{{ filename }}
</span>-->
<input
type="file"
#fileUpload
id=""
name="fileUpload"
accept="image/*,application/pdf"
style="display:none;"
/>
</div>
I assume you are using blob, so after you created a link, with or without class="button", you should simply bind a function on (click) event with some identification property, and get it from your server, then, tell your httpget that the response type is blob.
With angular httpclient looks something like this:
//injected httpService from angular
this.httpClient.get('your controller', { responseType: blob}).subscribe( response => {
const a = document.createElement('a'); // get the element
const objectUrl = URL.createObjectURL(response); //create objecturl
a.href = objectUrl; //make the <a></a> link's href to this object url
a.download = 'any name you want to add';
a.click(); //imitate a click on it
//THE FOLLOWING STATEMENT IS ONLY FOR BE ABLE TO DOWNLOAD IT IN MS EDGE
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveOrOpenBlob(response, 'any name you want to add' + ".pdf");
}
URL.revokeObjectURL(objectUrl);
})
I think its not the perfect solution, but it worked for me.

Categories