Blob from Dataurl

Blob from DataURL?

User Matt has proposed the following code a year ago ( How to convert dataURL to file object in javascript? ) which might help you

EDIT: As some commenters reported, BlobBuilder has been deprecated some time ago. This is the updated code:

function dataURItoBlob(dataURI) {
// convert base64 to raw binary data held in a string
// doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code that does this
var byteString = atob(dataURI.split(',')[1]);

// separate out the mime component
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]

// write the bytes of the string to an ArrayBuffer
var ab = new ArrayBuffer(byteString.length);

// create a view into the buffer
var ia = new Uint8Array(ab);

// set the bytes of the buffer to the correct values
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}

// write the ArrayBuffer to a blob, and you're done
var blob = new Blob([ab], {type: mimeString});
return blob;

}

Convert dataURL/Buffer to blob

Here's a complete example for how to get from canvas to Pinata file upload result. I have included plenty of comments, and can explain further if something is unclear:

Files:


./package.json:

{
"name": "so-71458029",
"version": "0.1.0",
"description": "",
"type": "module",
"scripts": {
"compile": "tsc",
"dev": "ts-node --esm src/main.ts",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "MIT",
"devDependencies": {
"@types/node": "^17.0.21",
"ts-node": "^10.7.0",
"typescript": "^4.6.2"
},
"dependencies": {
"canvas": "^2.9.0",
"dotenv": "^16.0.0",
"form-data": "^4.0.0",
"node-fetch": "^3.2.3"
}
}


./tsconfig.json:

{
"compilerOptions": {
// Node 16 ESM options
// Ref: https://github.com/microsoft/TypeScript/wiki/Node-Target-Mapping#node-16
"lib": ["es2021"],
"module": "esnext",
"moduleResolution": "node",
"target": "es2021",

// Compatibility
"allowSyntheticDefaultImports": true,

// Suggestion: strict options for safety
"strict": true,
"exactOptionalPropertyTypes": true,
"isolatedModules": true,
"noUncheckedIndexedAccess": true,
"useUnknownInCatchVariables": true,

// output config
"declaration": true,
"outDir": "dist",
},
"include": [
"./src/**/*"
]
}


./.env:

PINATA_JWT=your_actual_pinata_jwt


./src/canvas.ts:

/*
import {createCanvas, type Canvas} from 'canvas';
^^^^^^^^^^^^
SyntaxError: Named export 'createCanvas' not found.
The requested module 'canvas' is a CommonJS module,
which may not support all module.exports as named exports.
*/
import _canvas, {type Canvas} from 'canvas';
import FormData from 'form-data';
import {Headers} from 'node-fetch';

const {createCanvas} = _canvas;

/** https://github.com/form-data/form-data/tree/v4.0.0#usage */
export function createRequestInitFromCanvas (canvas: Canvas): {
body: FormData;
headers: Headers;
} {
const form = new FormData();

// Stream the canvas image data. (Other formats available.)
// https://github.com/Automattic/node-canvas/tree/v2.9.0#canvascreatepngstream
const pngStream = canvas.createPNGStream();

const fileOptions: FormData.AppendOptions = {
contentType: 'image/png',
filename: 'canvas.png',
};

form.append('file', pngStream, fileOptions);

return {
body: form,
headers: new Headers(form.getHeaders()),
};
}

/** https://github.com/Automattic/node-canvas/tree/v2.9.0#quick-example */
export function getExampleCanvas (): Canvas {
const canvas = createCanvas(200, 200);
const ctx = canvas.getContext('2d');

// Write "Awesome!"
ctx.font = '30px Impact';
ctx.rotate(0.1);
ctx.fillText('Awesome!', 50, 100);

// Draw line under text
const text = ctx.measureText('Awesome!');
ctx.strokeStyle = 'rgba(0,0,0,0.5)';
ctx.beginPath();
ctx.lineTo(50, 102);
ctx.lineTo(50 + text.width, 102);
ctx.stroke();

return canvas;
}


./src/main.ts:

import 'dotenv/config';
import assert from 'assert/strict';
import {type Canvas} from 'canvas';
import {default as fetch, Request, Response} from 'node-fetch';
import {createRequestInitFromCanvas, getExampleCanvas} from './canvas.js';

async function createResponseError (response: Response): Promise<Error> {
let body: any = '';

try {
body = await response.text();
body = JSON.parse(body);
}
catch {/* empty */}

if (!body) body = null;

const json = JSON.stringify({
status: response.status,
headers: Object.fromEntries([...response.headers].sort()),
body,
}, null, 2);

return new Error(`Response error:\n${json}`);
}

/** https://docs.pinata.cloud/api-pinning/pin-file#response */
type PinataFileUploadResponse = {
IpfsHash: string;
PinSize: number;
/** ISO 8601 datetime */
Timestamp: string;
};

/** https://docs.pinata.cloud/api-pinning/pin-file */
async function pinCanvasImage (pinataJWT: string, canvas: Canvas): Promise<PinataFileUploadResponse> {
const {body, headers} = createRequestInitFromCanvas(canvas);

// https://docs.pinata.cloud/#connecting-to-the-api
// https://docs.pinata.cloud/#your-api-keys
headers.set('Authorization', `Bearer ${pinataJWT}`);

// See more body options and examples at:
// https://docs.pinata.cloud/api-pinning/pin-file#body

// https://docs.pinata.cloud/api-pinning/pin-file#pinataoptions-optional
// const pinataOptions = {};
// body.append('pinataOptions', JSON.stringify(pinataOptions));

// https://docs.pinata.cloud/api-pinning/pin-file#pinatametadata-optional
// const pinataMetadata = {};
// body.append('pinataMetadata', JSON.stringify(pinataMetadata));

const request = new Request('https://api.pinata.cloud/pinning/pinFileToIPFS', {
method: 'POST',
body,
headers,
});

const response = await fetch(request);
if (!response.ok) {
const err = await createResponseError(response);
throw err;
}
return response.json() as Promise<PinataFileUploadResponse>;
}

async function main () {
const {PINATA_JWT} = process.env;

// Ensure that the environment variable exists
// https://nodejs.org/api/assert.html#assertokvalue-message
assert.ok(PINATA_JWT);

const canvas = getExampleCanvas();

const result = await pinCanvasImage(PINATA_JWT, canvas);
console.log(result);
}

main();


Run it::

Node/npm versions:

$ node --version
v16.14.0
$ npm --version
8.3.1

Run using:

$ npm install
$ npm run dev

HTML5 / Javascript - DataURL to Blob & Blob to DataURL

Nevermind, it ended up working after sticking to the instructions in this thread Display image from blob using javascript and websockets and making my server forward raw (yet) unmodified BinaryWebSocketFrames.

Now I'm still fighting bad performance of the canvas (<1fp) but that might become subject of a new thread.

Blob's DataUri vs Base64 string DataUri

Here is the answer. Looks like it is an encoding issue. In order to convert/decode Base64 string to binary(UInt8Array/byte) using atob is not enough. After using atob it is required to use UTF-16 character code: and we achieve this by using charCodeAt function for every character in the decoded string. As a result we get UTF-16 encoded binary string which is definately working. Just create a Blob and then call URL.createObjectURL.



Related Topics



Leave a reply



Submit