preface
This article in the way of graphic and text in simple binary concept, the previous concept description is more boring, but very important! Hope everyone patience to look down, there is a surprise behind, will let you tiger body a shock ~😉
Blob
Blob represents a large object of binary type, usually a video, sound, or multimedia file, and in javaScript a Blob represents an immutable, raw data-like file object.
Its constructors are as follows:
new Blob(blobParts, options);
Copy the code
lobParts
: An array type that can hold any number of arraysArrayBuffer.ArrayBufferView.BloborDOMString(encoded as UTF-8), concatenating them to form the data of the Blob object.options
: Optional, used to set the properties of the BLOb object. You can specify the following two properties:- Type: stores the contents of the array in the BLOBMIMEType (default “”).
- Endings: Used to specify how the string containing the line end \n is written. A value ofnativeIndicates that the line terminator is changed to a newline suitable for the host operating system file system (the default istransparentIndicates that the terminator saved in the BLOB is kept unchanged.)
DOMString is a UTF-16 string. Because JavaScript already uses such strings, DOMString maps directly to a String.Copy the code
ArrayBuffer (binary data buffer), ArrayBufferView (Array-like view of binary data buffer)Copy the code
The following is an example 👇
- Create a BLOB object that contains a DomString object
const blob = new Blob(['<div>john</div>'] and {type: 'text/xml' });
console.log(blob); // Blob {size: 15, type: "text/xml"}
Copy the code
- Creates a BLOB object that contains an ArrayBuffer object
var abf = new ArrayBuffer(8);
const blob = new Blob([abf], { type: 'text/plain' });
console.log(blob); // Blob {size: 8, type: "text/plain"}
Copy the code
- Create a BLOB object that contains an ArrayBufferView object
var abf = new ArrayBuffer(8);
var abv = new Int16Array(abf);
const blob = new Blob(abv, { type: 'text/plain' });
console.log(blob); // Blob {size: 4, type: "text/plain"}
Copy the code
attribute
Blob objects have two properties, as shown in the following table 👇 :
The property name | describe |
---|---|
size | The size of the data contained in the Blob object. The unit is byte. Read-only. |
type | A string indicating the MIME type of the data contained in the Blob object. If the type is unknown, the value is an empty string. Read-only. |
methods
slice(start:number, end:number, contentType:DOMString)
: array-likesliceMethod that splits the original Blob object into a new Blob object in the specified range and returns it, which can be used for slice upload- Start: starts the index. The default value is 0
- End: indicates the end index. The default value is the last index
- ContentType: The MIME type of the new Blob, which is an empty string by default
stream()
: returns an object that can read bloB contentsReadableStream.text()
: Returns aPromiseObject in UTF-8 format that contains all the contents of the BLOBUSVString.arrayBuffer()
: Returns aPromiseObject and contains all the contents of the BLOB in binary formatArrayBuffer.
Save the BLOB (or file) binary to formData for web requests (imageUrl, which can then fetch images, can be used for image presentation or later to send image addresses via webSocket)
File
A File object is a special Blob object that inherits all Blob properties and methods, but can also be used as a formData binary File upload
Obtain File:
Here we use input and drag and drop to select multiple images respectively 👇:
- Input Gets the local file
<input type="file" multiple id="f" />
<script></script>
Copy the code
- Drag and drop to obtain
<div id="content" ondrop="drop(event)" ondragover="allowDrop(event);" /> <script></script> <style type="text/css"> #content { width: 500px; height: 500px; border: 1px solid brown; } </style> Copy the code
Add a multiple attribute to the input element to allow the user to select multiple files. Each file selected by the user is a file object. A FileList object is a list of these File objects.
attribute
File object properties, see the following table 👇 :
The property name | describe |
---|---|
lastModified | Reference file last modified date |
name | File name or file path |
size | Returns the size of the file in bytes |
type | The MIME type of the file |
methods
File objects have no instance methods of their own, and since they inherit from Blob objects, they can use slice(), the instance method of Blob.
Data buffer
From XHR, File API, Canvas, etc., read a large string of byte streams. If you use Array in JS to store, it is wasteful and inefficient. In programming, a data buffer (or buffer for short) is a storage area in physical memory that manipulates binary data (faster than hard disk drive access) and is used to store temporary data as it is moved from one location to another. The interpreter reads rows with the help of the memory buffer that stores binary data. There is a running file in main memory, and if the interpreter had to return the file to read every bit, the execution would take a lot of time. To prevent this, JavaScript uses a data buffer that stores bits together and then sends them all together to the interpreter. This way, the JavaScript interpreter does not have to worry about retrieving files from file data. This approach saves execution time and speeds up the application. Various buffer classes perform valid binary operations on data, including File, Blob, ArrayBuffer, and Array. The method selected determines the internal structure of the buffer in memory.
Buffer
Buffers are objects provided by Node.js, not the front-end. A Buffer is similar to an array of integers, but it corresponds to a chunk of raw memory outside the V8 heap memory.
ArrayBuffer, ArrayBufferView
ArrayBuffer
An ArrayBuffer is a raw buffer of fixed-length binary data. Its purpose is to allocate a contiguous area of memory for storing data, so it is much faster than Array in JS for high-density access operations such as audio data. The purpose of an ArrayBuffer is to be written to memory in advance as a data source, so its length is fixed
Let’s take a look at what ArrayBuffer does:
The constructor of the ArrayBuffer object is as follows (length indicates the length of the ArrayBuffer)👇:
ArrayBuffer(length);
Copy the code
The difference between Array and ArrayBuffer 👇 :
Array | ArrayBuffer |
---|---|
You can put numbers, strings, booleans, objects, arrays, and so on | Only 0 and 1 binary data can be stored |
The data is placed in the heap | Data is placed on the stack, so fetching data is faster |
You can add or subtract as you like | Read-only, fixed size after initialization, whether the buffer is empty or not, can only be written with TypedArrays, Dataview |
attribute
See the following table 👇 for the properties of the ArrayBuffer object:
The property name | describe |
---|---|
byteLength | Represents the size of an ArrayBuffer |
methods
slice
: takes two parameters 👉beginThat’s the beginning,endIndicates the end point. The ArrayBuffer () method returns a new ArrayBuffer whose contents are byte copies of the ArrayBuffer, from begin (included) to end (not included).
An ArrayBuffer cannot operate directly, but rather through TypedArray or DataView objects, which convert the data in the buffer into arrays of various data types and read and write the contents of the buffer in these formats. 👇
ArrayBufferView
Since an ArrayBuffer object doesn’t provide any way to read or write directly to memory, and an ArrayBufferView object is actually a view based on an ArrayBuffer object that specifies the basic processing unit for raw binary data, Read the contents of an ArrayBuffer object through an ArrayBufferView object. TypedArrays (TypedArrays) and dataviews are instances of ArrayBufferView.
TypedArrays
TypedArrays are a new concept in JavaScript designed to access raw binary data. TypedArrays are essentially the same as arraybuffers, except that they can read and write
The types of the array are: 👇 :
The name of the | Size (in bytes) | instructions |
---|---|---|
Int8Array | 1 | An 8-bit signed integer |
Uint8Array | 1 | An 8-bit unsigned integer |
Int16Array | 2 | 16 – bit signed integer |
Uint16Array | 2 | 16 – bit unsigned integer |
Int32Array | 4 | 32 – bit signed integer |
Uint32Array | 4 | 32 – bit unsigned integer |
Float32Array | 4 | 32-bit floating point number |
Float64Array | 8 | 64-bit floating point number |
Type conversion is shown in 👇 :Here are some code examples to show how to convert:
// Create an 8-byte ArrayBuffer
var b = new ArrayBuffer(8);
// Create a view v1 that points to b, of type Int32, starting with the default byte index 0 and ending at the end of the buffer
var v1 = new Int32Array(b); // Int32Array(2) [0, 0]
v1[0] = 1
console.log(v1); // Int32Array(2) [1, 0]
// Create a view v2 pointing to B, of type Uint8, starting with byte index 2 and ending at the end of the buffer
var v2 = new Uint8Array(b, 2); // Uint8Array(6) [0, 0, 0, 0, 0, 0]
// Create a view v3 pointing to b, of type Int16, starting with byte index 2 and of length 2
var v3 = new Int16Array(b, 2.2); // Int16Array(2) [0, 0]
Copy the code
Because normal Javascript arrays use a Hash lookup, typed arrays access fixed memory directly, so they’re faster than traditional arrays! At the same time, typed arrays naturally handle binary data, which is an inherent advantage for XMLHttpRequest, Canvas, webGL, and other technologies.
Fetch audio resources -> ArrayBuffer -> TypedArray -> Join into a TypedArray -> ArrayBuffer -> Blob -> Object URLCopy the code
DataView
DataView objects can read and store different types of binary data anywhere in the ArrayBuffer.
The syntax for creating DataView is as follows:
var dataView = new DataView(DataView(Buffer, byteOffset[optional], byteLength[optional]);Copy the code
attribute
The DataView object has three properties, as shown in the following table 👇 :
The property name | describe |
---|---|
buffer | Said ArrayBuffer |
byteOffset | Refers to the offset at the beginning of the buffer |
byteLength | Refers to the length of the buffer portion |
methods
setint8()
From:DataViewStores an 8-bit number (one byte) at the specified byte offset starting position.getint8()
From:DataViewGets an 8-bit number (one byte) at the specified byte offset starting position.
GetInt16, getUint16, getInt32, getUint32… Use method is consistent, here is not an example
Usage: 👇
let buffer = new ArrayBuffer(32);
let dataView = new DataView(buffer,0);
dataView.setInt16(1.56);
dataView.getInt16(1); / / 56
Copy the code
FileReader
The contents of blobs or file objects cannot be accessed directly, but if you want to read them and convert them into data in other formats, you can do so using the FileReader object API
readAsText(Blob)
: Converts blobs to text stringsreadAsArrayBuffer(Blob)
: Converts bloBS to ArrayBuffer format datareadAsDataURL()
: Converts Blob to Base64 format DataURL
Use the following 👇:
const blob = new Blob(['<xml>foo</xml>'] and {type: 'text/xml' });
console.log(blob); // Blob(14) {size: 14, type: "text/xml"}
const reader = new FileReader();
reader.onload = () = > {
console.log(reader.result);
};
reader.readAsText(blob); // <xml>foo</xml>
reader.readAsArrayBuffer(blob); // ArrayBuffer(14) {}
reader.readAsDataURL(blob); // data:text/xml; base64,PHhtbD5mb288L3htbD4
Copy the code
Here we try to read the contents of a file as a string:
<input type="file" id='f' />
<script>
document.getElementById('f').addEventListener('change'.function (e) {
var file = this.files[0];
// First, you need to create an instance of FileReader.
const reader = new FileReader();
reader.onload = function () {
// Call back when the load is complete
const content = reader.result;
console.log(content);
}
reader.readAsText(file); // Convert the bloB to a text string to read
}, false);
</script>
Copy the code
Read the following result 👇:
BlobURL
BlobURL (ObjectURL) is a pseudo protocol that can only be generated internally by browsers. We know that SRC attributes of script/img/video/iframe tags and background urls can be displayed by URL and base64. We can also convert bloBs or files to urls to generate bloburls to display images. BlobURL allows BLOBs and Files to be used as URL sources for images, downloading binary data links, and so on.
Image display 👇:
<div id="content">
<input type="file" multiple id="f" />
</div>
<script>
const elem = document.getElementById('f');
const content = document.getElementById('content');
// Encapsulate a method to transform BlobUrl depending on the browser :file can be either a file object or a Blob object
const getObjectURL = (file) = > {
let url;
if (window.createObjectURL) {
url = window.createObjectURL(file);
} else if (window.URL) {
url = window.URL.createObjectURL(file);
} else if (window.webkitURL) {
url = window.webkitURL.createObjectURL(file);
}
return url;
};
elem.onchange = function (event) {
const files = event.target.files;
const file = files[0];
const img = document.createElement('img');
img.src = getObjectURL(file);
content.appendChild(img);
};
</script>
Copy the code
When we look at the MM image element on the Demo page, we see that its URL address is neither a traditional HTTP nor a Base64 URL, but rather a blob: string that starts with the address bar and can be checked by placing it in the address bar.
File download 👇:
<body>
<button onclick="download()">download.txt</button>
<script>
const getObjectURL = (file) = > {
let url;
if (window.createObjectURL) {
url = window.createObjectURL(file);
} else if (window.URL) {
url = window.URL.createObjectURL(file);
} else if (window.webkitURL) {
url = window.webkitURL.createObjectURL(file);
}
return url;
};
function download() {
const fileName = 'download.txt';
const myBlob = new Blob(['johnYu'] and {type: 'text/plain' });
downloadFun(fileName, myBlob);
}
function downloadFun(fileName, blob) {
const link = document.createElement('a');
link.href = getObjectURL(blob);
link.download = fileName;
link.click();
link.remove();
URL.revokeObjectURL(link.href);
}
</script>
</body>
Copy the code
Click the button to download the document, which reads :johnYu
I’m not going to callrevokeObjectURL
When visitingchrome://blob-internals/
You can see a list of the current internal BLOb files:BlobUrl that is no longer used is automatically cleared later (as is closing the browser), but is best usedURL.revokeObjectURL(url)
Remove them manually:
URL.revokeObjectURL('the blob: http://127.0.0.1:5500/d2a9a812-0dbf-41c5-a96b-b6384d33f281');
Copy the code
After execution, visit Chrome again ://blob-internals/ You can see that the file has been cleared
dataURL
DataURL allows content creators to embed smaller files into documents. This is similar to normal URL usage
The syntax format is 👇 :
data:[<mediatype>][;base64],data
Copy the code
data
: prefixmediatype
Indicates the data type, which is oneMIMEA string of type, such as image/ JPEG, representing a JPEG image file. If omitted, the default value istext/plain; charset=US-ASCII.base64
: flag bit (optional if text)data
: Data itself
How do I get the DataUrl
- The method used in the above example, readAsDataURL(), converts the Blob to Base64 DataUrl;
- Use native
Web API
Encoding/decoding
There are two functions in Javascript that encode and decode Base64 strings, atOB and BTOA. Both work only on the Data in the Data URL.
btoa('<xml>foo</xml>') // "PHhtbD5mb288L3htbD4="
atob('PHhtbD5mb288L3htbD4=') // "<xml>foo</xml>"
Copy the code
- Atob (): Is responsible for decoding strings already encoded in Base64.
- Btoa (): Converts the binary string to base64 encoded
ASCII
A string.
- Canvas toDataURL method:
Canvas provides a toDataURL method to get Canvas drawn content and convert it to Base64 format.
<body>
<canvas id="canvas" width="200" height="50"></canvas>
<textarea id="content" style="width: 200px; height: 200px"></textarea>
<script>
var canvas = document.getElementById('canvas');
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
// Canvas drawing
ctx.font = 'Bold 20px Arial';
ctx.textAlign = 'left';
ctx.fillStyle = 'purple';
ctx.fillText('johnYu'.10.30);
// Get the Data URL
document.getElementById('content').value = canvas.toDataURL();
}
</script>
</body>
Copy the code
As shown in the figure below, the content in the text box is the Base64 format of the content drawn on canvas.
If we return the previous resultdata:text/xml; base64,PHhtbD5mb288L3htbD4=
In the browser address bar, you can see the displayed content.
The use of DataUrl
- Since it can be used as aURL substitute, DataURL and BlobUrl can be used in script/img/video/iframe tag SRC attributes and background urls. The usage is basically the same as BlobUrl
elem.onchange
Make the following modifications
<body>
<div id="content">
<input type="file" multiple id="f" />
</div>
<script>
const elem = document.getElementById('f');
const content = document.getElementById('content');
elem.onchange = function (event) {
const files = event.target.files;
const file = files[0];
const img = document.createElement('img');
- img.src = getObjectURL(file);
+ const reader = new FileReader();
+ reader.onload = function () {
+ img.src = reader.result;
+};
+ reader.readAsDataURL(file);
content.appendChild(img);
};
</script>
</body>
Copy the code
- Because the data itself is represented by a URL, it can be stored in a Cookie and passed to the server.
- When the size of the image is too small to justify occupying an HTTP session.
- When access to external resources is cumbersome or limited
- Dataurls are not cached by browsers, but a small percentage are cached by CSS. In the following example, the use of dataurls is scenariospecific. It prevents the small background image from generating an HTTP request on its own, and the small image can be cached by the browser along with the CSS file and reused instead of being loaded every time it is used. As long as the image is not too large and not used repeatedly in CSS files, the DataUrl method can reduce page load times and improve the user’s browsing experience.
background-image: url("data:image/gif; base64,R0lGODlhAwADAIAAAP///8zMzCH5BAAAAAAALAAAAAADAAMAAAIEBHIJBQA7");
Copy the code
- Use as a download connection
<script>
const createDownload = (fileName, content) = > {
const blob = new Blob([content]);
const reader = new FileReader();
const link = document.createElement('a');
link.innerHTML = fileName;
link.download = fileName;
reader.onload = () = > {
link.href = reader.result;
document.getElementsByTagName('body') [0].appendChild(link);
};
reader.readAsDataURL(blob);
};
createDownload('download.txt'.'johnYu');
</script>
Copy the code
Click the a TAB and download the TXT file with the text content of johnYu. The BlobURL below can also be implemented 👇
The difference between
BlobURL is basically the same as DataUrl and can be checked by placing it in the address bar or used as a normal URL.
However, there are the following differences.
- BlobUrl is always a unique string, even if you pass the same Blob each time, a different BlobUrl will be generated each time; DataUrl values change with BLOB;
- As far as BlobUrl is concerned, it does not represent the data itself, the data is stored in the browser, and BlobUrl is just the key to access it. The data remains valid until the browser is closed or cleared manually. And the DataUrl is the directly encoded data itself. So even if you pass BlobUrl to a server and so on, you can’t access the data. Post DataUrl can still be accessed in the address bar after closing the browser, but BlobUrl cannot be accessed
- BlobUrl is generally short in length, but dataurls tend to be quite long because they store base64 encoded data directly from images (base64 encoded data is usually one-third larger than binary images). , so when it comes to explicit large images, using BlobUrl gives you better possibilities, speed and memory than DataUrl
- BlobUrl makes it easy to get source data using XMLHttpRequest (xhr.responseType = ‘blob’). For dataurls, not all browsers support XMLHttpRequest to retrieve source data
<body>
<button onclick="download1()">XMLHttpRequest download</button>
<button onclick="download2()">The fetch download</button>
<img id="img" />
<script>
var eleAppend = document.getElementById('forAppend');
const url = 'https://sf3-ttcdn-tos.pstatp.com/img/user-avatar/9ecb4e119c26e64b8b4ec5258f159b3b~300x300.image';
const pingan = document.querySelector('#pingan');
function download1() {
const xhr = new XMLHttpRequest();
xhr.open('get', url, true);
xhr.responseType = 'blob';
xhr.onload = function () {
if (this.status == 200) {
renderImage(this.response); }}; xhr.send(null);
}
function download2() {
fetch(url)
.then((res) = > {
return res.blob();
})
.then((myBlob) = > {
renderImage(myBlob);
});
}
function renderImage(blob) {
window.URL = window.URL || window.webkitURL;
var img = document.getElementById('img');
img.onload = function (e) {
window.URL.revokeObjectURL(img.src); // Clear release
};
img.src = window.URL.createObjectURL(blob);
}
</script>
</body>
Copy the code
- BlobUrl can also be used as a web address for other resources, such as HTML files, JSON files, etc. To ensure that the browser can correctly parse the file type returned by BlobUrl, specify the corresponding type when creating the Blob object
const createDownload = (fileName, content) = > {
const blob = new Blob([content], { type: 'text/html' });
const link = document.createElement('a');
link.innerHTML = fileName;
link.download = fileName;
link.href = getObjectURL(blob);
document.getElementsByTagName('body') [0].appendChild(link);
};
createDownload('download.html'.'<button>foo</button>');
Copy the code
6. Dataurls are not cached by browsers, which means they are downloaded every time such a page is visited. This is a matter of efficiency – especially when the image is used extensively throughout the site. But a small portion can be cached via CSS
canvas
The Canvas element is responsible for setting up a region on the page that you can then dynamically draw in using JavaScript.
methods
toDataURL(type, encoderOptions))
: returns the DataUrl in the specified format. This method takes two optional arguments- Type: indicates the image format. The default value is image/ PNG
- EncoderOptions: Indicates the quality of the image. If the image format is image/ JPEG or image/webp, the image quality can be selected from 0 to 1. If the value is outside the range, the default value of 0.92 will be used and other parameters will be ignored.
toBlob(callback, type, encoderOptions)
: Creates Blob objects that display canvas images. The default image type is Image/PNG and the resolution is96dpi- Callback: The argument is the callback function of the BLOb object
getImageData(x,y,width,height)
: Returns an ImageData object that copies the pixel data of the specified rectangle on the canvas.- X: the x-coordinate of the upper-left position where the replication begins.
- Y: the y-coordinate of the upper-left position where the replication begins.
- Width: Width of the rectangle area to be copied.
- Height: The height of the rectangle region to be copied.
putImageData(imgData,x,y,dirtyX,dirtyY,dirtyWidth,dirtyHeight)
: puts the ImageData (from the specified ImageData object) back on the canvas.- ImgData: Specifies the ImageData object to be put back into the canvas.
- X: The x-coordinate of the upper-left corner of the ImageData object, in pixels.
- Y: The y coordinate of the upper-left corner of the ImageData object, in pixels.
- DirtyX: optional. Horizontal value (x), in pixels, the position of the image on the canvas.
- DirtyY: optional. Horizontal value (y), in pixels, the position of the image on the canvas.
- DirtyWidth: optional. The width used to draw the image on the canvas.
- DirtyHeight: optional. The height used to draw the image on the canvas.
Application scenarios
When we need to obtain the content of canvas, we can use toDataURL and toBlob attributes (which can be used for signature, image clipping, image compression and other scenes). PutImageData and getImageData can be used for image grayscale or replication (see the following section of application scenarios 👇).
Get content:
<body>
<div id="content">
<button onclick="drawnImg()">The plot</button>
<button onclick="getImg()">Access to images</button>
<canvas style="border: 1px solid black" id="drawing" width="200" height="200">A drawing of something.</canvas>
<img src="./timg.jpg" alt="" />
</div>
<script>
var drawing = document.getElementById('drawing');
var quality = 0.3;
const imgType = 'image/jpeg';
var drawnImg = function () {
if (drawing.getContext) {
var context = drawing.getContext('2d');
// Get the image's data URI
var image = document.images[0];
context.drawImage(image, 20.20.100.100); }};var getImg = async function () {
const content = getContent('base64');
console.log(content);
const content1 = await getContent('file');
console.log(content1);
};
var getContent = function (type) {
switch (type) {
case 'base64':
{
const imgURL = drawing.toDataURL(imgType, quality);
return imgURL;
}
break;
case 'file':
{
// Convert to file format
return new Promise((resolve) = > {
drawing.toBlob(
(blob) = > {
resolve(blob);
},
imgType,
quality
);
});
}
break; }};</script>
</body>
Copy the code
Relationship and transformation
String → Uint8Array
var str = 'ab';
console.log(Uint8Array.from(str.split(' '), (e) = > e.charCodeAt(0))); // Uint8Array(2) [97, 98]
Copy the code
Uint8Array → String
var u8 = Uint8Array.of(97.98);
console.log(Array.from(u8, (e) = > String.fromCharCode(e)).join(' ')); // ab
Copy the code
String → DataUrl
var str = 'ab';
console.log('data:application/octet-stream; base64,' + btoa(str)); // data:application/octet-stream; base64,YWI=
Copy the code
DataUrl -> string
var data = 'data:application/octet-stream; base64,YWI=';
console.log(atob(data.split(', ') [1])); // ab
Copy the code
Uint8Array -> ArrayBuffer
var u8 = Uint8Array.of(1.2);
console.log(u8.buffer); // ArrayBuffer(2) {}
Copy the code
ArrayBuffer -> Uint8Array
var buffer = new ArrayBuffer(2);
console.log(new Uint8Array(buffer)); // Uint8Array(2) [0, 0]
Copy the code
ArrayBuffer -> DataView
var buffer = new ArrayBuffer(2);
var dataView = new DataView(buffer, 0); // DataView(2) {}
Copy the code
DataView -> ArrayBuffer
console.log(dataView.buffer); // ArrayBuffer(2) {}
Copy the code
ArrayBuffer – a Blob
var buffer = new ArrayBuffer(32);
var blob = new Blob([buffer]); // Blob {size: 32, type: ""}
Copy the code
UintXXArray – a Blob
var u8 = Uint8Array.of(97.32.72.101.108.108.111.32.119.111.114.108.100.33);
var blob = new Blob([u8]);
Copy the code
String → Blob
var blob = new Blob(['Hello World! '] and {type: 'text/plain'}); // Blob {size: 12, type: "text/plain"}
Copy the code
New Blob() to Blob
DataUrl -> blob
var data = 'data:application/octet-stream; base64,YWI=';
function dataURLtoBlob(dataurl) {
var arr = dataurl.split(', '),
mime = arr[0].match(/ : (. *?) ; /) [1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], { type: mime });
}
console.log(dataURLtoBlob(data)); // Blob {size: 2, type: "application/octet-stream"}
Copy the code
The Blob –
The FileReader Api is used to convert readAsText(Blob), readAsArrayBuffer(Blob), and readAsDataURL(), but asynchronously
var blob = new Blob(['a Hello world! '] and {type: 'text/plain' });
var reader = new FileReader();
reader.readAsText(blob, 'utf-8');
reader.onload = function (e) {
console.info(reader.result); // a Hello world!
};
reader.onerror = function (e) {
console.error(reader.error);
};
Copy the code
You can use promises to do multiple conversions
var blob = new Blob(['a Hello world! '] and {type: 'text/plain' });
function read(blob) {
var fr = new FileReader();
var pr = new Promise((resolve, reject) = > {
fr.onload = (eve) = > {
resolve(fr.result);
};
fr.onerror = (eve) = > {
reject(fr.error);
};
});
return {
arrayBuffer() {
fr.readAsArrayBuffer(blob);
return pr;
},
binaryString() {
fr.readAsBinaryString(blob);
return pr;
},
dataURL() {
fr.readAsDataURL(blob);
return pr;
},
text() {
fr.readAsText(blob);
returnpr; }}; }var pstr1 = read(blob).binaryString();
var pstr2 = read(blob)
.arrayBuffer()
.then((e) = > Array.from(new Uint8Array(e), (e) = > String.fromCharCode(e)).join(' '));
Promise.all([pstr1, pstr2]).then((e) = > {
console.log(e[0]); // a Hello world!
console.log(e[0] === e[1]); // true
});
Copy the code
Application scenarios
Image graying
This is mainly used to convert canvas and imageData
<body>
<button onclick="drawngray()">Black and white images</button>
<img src="./syz.jpg" alt="" />
<canvas id="myCanvas">canvas</canvas>
<script>
var drawngray = function () {
var myCanvas = document.getElementById('myCanvas');
if (myCanvas.getContext) {
var context = myCanvas.getContext('2d');
var image = document.images[0];
// Dynamically set the canvas size
myCanvas.width = image.width;
myCanvas.height = image.height;
var imageData, data, i, len, average, red, green, blue, alpha;
// Draw the original image
context.drawImage(image, 0.0);
// get image data
imageData = context.getImageData(0.0, image.width, image.height);
data = imageData.data;
for (i = 0, len = data.length; i < len; i += 4) {
red = data[i];
green = data[i + 1];
blue = data[i + 2];
// alpha = data[i + 3];
// Find the RGB average value
average = Math.floor((red + green + blue) / 3);
// Set the color value, opacity unchanged
data[i] = average;
data[i + 1] = average;
data[i + 2] = average;
}
// Write back image data and display results
imageData.data = data;
context.putImageData(imageData, 0.0); }};</script>
</body>
Copy the code
The getImageData except time and putImageData can also be used as a cavas photo copy: https://www.w3school.com.cn/tiy/t.asp?f=html5_canvas_getimagedataCopy the code
Image compression
To achieve image compression in the front end, we can use the toDataURL() method provided by the Canvas object
compress.js
const MAX_WIDTH = 800; // Maximum width of image
function compress(base64, quality, mimeType) {
let canvas = document.createElement('canvas');
let img = document.createElement('img');
img.crossOrigin = 'anonymous';
return new Promise((resolve, reject) = > {
img.src = base64;
img.onload = () = > {
let targetWidth, targetHeight;
if (img.width > MAX_WIDTH) {
targetWidth = MAX_WIDTH;
targetHeight = (img.height * MAX_WIDTH) / img.width;
} else {
targetWidth = img.width;
targetHeight = img.height;
}
canvas.width = targetWidth;
canvas.height = targetHeight;
let ctx = canvas.getContext('2d');
ctx.clearRect(0.0, targetWidth, targetHeight); // Clear the canvas
ctx.drawImage(img, 0.0, canvas.width, canvas.height);
// Base64 compressed by toDataURL
let imageData = canvas.toDataURL(mimeType, quality / 100);
resolve(imageData);
};
});
}
Copy the code
test.html
<body>
<input type="file" accept="image/*" onchange="loadFile(event)" />
<script src="./compress.js"></script>
<script>
function dataUrlToBlob(base64) {
var arr = base64.split(', '),
mime = arr[0].match(/ : (. *?) ; /) [1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], { type: mime });
}
function uploadFile(url, blob) {
let formData = new FormData();
let request = new XMLHttpRequest();
// Encapsulate to FormData for file upload
formData.append('image', blob);
request.open('POST', url, true);
request.send(formData);
}
const loadFile = function (event) {
const reader = new FileReader();
reader.onload = async function () {
let compressedDataURL = await compress(reader.result, 90.'image/jpeg');
// Convert base64 into Blob objects after compression to reduce the amount of data transferred
let compressedImageBlob = dataUrlToBlob(compressedDataURL);
uploadFile('https://httpbin.org/post', compressedImageBlob);
};
// Get the image file selected by the user and convert it to base64 by FileReader
reader.readAsDataURL(event.target.files[0]);
};
</script>
</body>
Copy the code
Shard to upload
<body>
<input type="file" name="file" onchange="selfile();" />
<script>
const url = 'https://httpbin.org/post';
/ * * *@param File Original file *@param ChunkSize Default size of each uploaded fragment */
async function chunkedUpload(file, chunkSize = 1024 * 1024 * 5) {
// Split the file into chunkSize chunks and upload only the chunkSize chunks per request
for (let start = 0; start < file.size; start += chunkSize) {
// File objects inherit from Blob objects, so large files can be sliced using the slice method
const chunk = file.slice(start, start + chunkSize + 1);
const fd = new FormData();
fd.append('data', chunk);
await fetch(url, { method: 'post'.body: fd })
.then((res) = > res.text())
.then((res) = > console.log(res)); // Prints the upload result}}function selfile() {
let file = document.querySelector('[name=file]').files[0];
// Customize the fragment size
const LENGTH = 1024 * 1024 * 1;
chunkedUpload(file, LENGTH);
}
</script>
</body>
Copy the code
After the server receives these slices, it can concatenate them. Here is an example of PHP concatenating slices:
$filename = './upload/' . $_POST['filename'];// Determine the file name for the upload
// If there is no file in the first upload, create a file. After uploading, just append data to this file
if(! file_exists($filename)){ move_uploaded_file($_FILES['file'] ['tmp_name'],$filename);
}else{
file_put_contents($filename,file_get_contents($_FILES['file'] ['tmp_name']),FILE_APPEND);
echo $filename;
}
Copy the code
Remember to modify the server configuration of nginx when testing, otherwise Large files may prompt 413 Request Entity Too Large error.
server {
// ...
client_max_body_size 50m;
}
Copy the code
Refer to the article 📜
❤️ Understand DOMString, Document, FormData, Blob, File, and ArrayBuffer data types
❤️ Talk about the binary family of JS: Blob, ArrayBuffer and Buffer
❤️ Blob you don’t know
Extension 🏆
If you find this article helpful, check out my other articles at ❤️ :
Introductory notes | fast 🚀 👍 vue3 practical experience
👍 10 simple tips to make your vue.js code more elegant 🍊
👍 Close contact with websocket🚀
👍 5 Design patterns to know for Web development
👍 Data structures Web development should know about
👍 How do I get screen, window and web page sizes in JavaScript