简体   繁体   中英

Text -> PNG -> ReadStream, all done on the front-end?

I'm not sure if this is even possible, but here's what I'm trying to do:

  1. Let the user enter some text
  2. Generate a PNG from that text
  3. Upload it to Pinata, which requires it to be in ReadStream format
  4. Do all of this on the front-end

I've managed to accomplish (1) and (2) using html2canvas .

The tricky part is (3). The reason it has to be in ReadStream format is because that's the format Pinata's SDK wants:

const fs = require('fs');
const readableStreamForFile = fs.createReadStream('./yourfile.png');
const options = {
    pinataMetadata: {
        name: MyCustomName,
        keyvalues: {
            customKey: 'customValue',
            customKey2: 'customValue2'
        }
    },
    pinataOptions: {
        cidVersion: 0
    }
};
pinata.pinFileToIPFS(readableStreamForFile, options).then((result) => {
    //handle results here
    console.log(result);
}).catch((err) => {
    //handle error here
    console.log(err);
});

I realize that this would be no problem to do on the backend with node, but I'd like to do it on the front-end. Is that at all possible? Or am I crazy?

I'm specifically using Vue if that matters.

For anyone interested the solution ended up being using fetch+blob:

    const generateImg = async () => {
      const canvas = await html2canvas(document.getElementById('hello'));
      const img = canvas.toDataURL('image/png');
      const res = await fetch(img);
      return res.blob();
    };

This blob can then be passed into a more manual version of their SDK:

const uploadImg = (blob: Blob) => {
    const url = `https://api.pinata.cloud/pinning/pinFileToIPFS`;

    const data = new FormData();
    data.append('file', blob);

    const metadata = JSON.stringify({
      name: 'testname',
    });
    data.append('pinataMetadata', metadata);

    const pinataOptions = JSON.stringify({
      cidVersion: 0,
    });
    data.append('pinataOptions', pinataOptions);

    return axios
      .post(url, data, {
        maxBodyLength: 'Infinity' as any, // this is needed to prevent axios from erroring out with large files
        headers: {
          // @ts-ignore
          'Content-Type': `multipart/form-data; boundary=${data._boundary}`,
          pinata_api_key: apiKey,
          pinata_secret_api_key: apiSecret,
        },
      })
      .then((response) => {
        console.log(response);
      })
      .catch((error) => {
        console.log(error);
      });
  };

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM