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
How to Ignore JavaScript Exceptions When Working with Webdriver (Htmlunit, Ruby Bindings)
Call Swift Function with JavaScript Using Uiwebview
D3.Js Drawing Geojson Incorrectly
Angularjs:Difference Between the $Observe and $Watch Methods
Installing a Local Module Using Npm
Is There a Max Number of Arguments JavaScript Functions Can Accept
What Are the Common Defenses Against Xss
Asynchronous Exception Handling with Bluebird Promises
Document.Getelementbyid VS Jquery $()
How to Update/Upsert a Document in Mongoose
Vue 2 - Mutating Props Vue-Warn
Sorting HTML Table with JavaScript
How to Detect the Screen Resolution with JavaScript
Why Is String Concatenation Faster Than Array Join
How to Get the Name of the Currently Running Function in JavaScript
Detect If Browser Tab Has Focus
Scrape HTML Generated by JavaScript with Python
How to Tell When a CSS Background Image Has Loaded? Is an Event Fired