Bunlong/next-qrcode

Can we have a download option, to download the QR code as png image?

VarshaKZBlocks opened this issue · 4 comments

I have a use case where i want to show the QR and i want to allow user to download that QRCode as png image which can be shared. Can we include such functionality?

Same here!

same here
has this been fixed?

as temporary solution, i used this:

function convertCanvasToFile(canvas: HTMLCanvasElement): Promise<File> {
    return new Promise((resolve, reject) => {
        canvas.toBlob((blob) => {
            if (blob) {
                const file = new File([blob], 'image.png', { type: 'image/png' });
                resolve(file);
            } else {
                reject(new Error('Failed to convert canvas to file'));
            }
        }, 'image/png');
    });
}

function downloadFile(file: File): void {
    const url = URL.createObjectURL(file);
    const link = document.createElement('a');
    link.href = url;
    link.download = file.name;
    link.style.display = 'none';
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
    URL.revokeObjectURL(url);
}

Then, somewhere create and render Canvas Element, storing value as useState:

const [value, setValue] = React.useState('Error value');

const { Canvas } = useQRCode();

and somewhere in your component:

<div className='hidden' id={'qr-canva'}>
    <Canvas
        text={value}
        options={{
            errorCorrectionLevel: 'M',
            margin: 3,
            scale: 4,
            width: 200,
        }}
    />
</div>

hidden i's just class from tailwind css to display: none.

So then create some function downloadQR and u can get png image:

// get the parent container
const canvas = document.getElementById('qr-canva')?.children[0] as HTMLCanvasElement;
if (canvas == null) {
   console.error('Canvas was not found');
   return;
}

// download image
convertCanvasToFile(canvas).then((file) => {
    downloadFile(file);
});

or share:

convertCanvasToFile(canvas).then((file) => {
        navigator.share({
            url: 'example.com',
            text: 'Share code',
            title: 'Share code',
            files: [file]
    })
});

Here is a simpler version:

Component:

    <div id="img">
      <Image
        text={"https://github.com/bunlong/next-qrcode"}
        options={{
          type: "image/png",
          errorCorrectionLevel: "M",
          margin: 3,
          scale: 4,
          width: 200,
          color: {
            dark: "#fff",
            light: "#000B40",
          },
        }}
      />
      <button onClick={downloadImage}>Download</button>
    </div>

JS function to add download functionality to the button:

  function downloadImage() {
    const image = document.getElementById("image");
    const div = document.getElementById("img");
    const image = div.querySelector("img");
    const a = document.createElement("a");
    
    a.href = image.src;
    a.download = "image.png";
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
  }