javascript
examples
examples.js⚡javascript
/**
* Blob and File API Examples
*
* Demonstrates working with binary data and files in JavaScript
*/
// =============================================================================
// 1. Creating Blobs
// =============================================================================
/**
* Create various types of Blobs
*/
function createBlobs() {
// Text Blob
const textBlob = new Blob(['Hello, World!'], { type: 'text/plain' });
console.log('Text Blob:', { size: textBlob.size, type: textBlob.type });
// JSON Blob
const data = { name: 'John', age: 30, hobbies: ['coding', 'reading'] };
const jsonBlob = new Blob([JSON.stringify(data, null, 2)], {
type: 'application/json',
});
console.log('JSON Blob:', { size: jsonBlob.size, type: jsonBlob.type });
// HTML Blob
const htmlContent = `
<!DOCTYPE html>
<html>
<head><title>Generated Page</title></head>
<body><h1>Hello from Blob!</h1></body>
</html>
`;
const htmlBlob = new Blob([htmlContent], { type: 'text/html' });
// CSV Blob
const csvContent = 'Name,Age,City\nJohn,30,NYC\nJane,25,LA\nBob,35,Chicago';
const csvBlob = new Blob([csvContent], { type: 'text/csv' });
// Binary Blob from Uint8Array
const bytes = new Uint8Array([72, 101, 108, 108, 111]); // "Hello" in ASCII
const binaryBlob = new Blob([bytes], { type: 'application/octet-stream' });
// Multi-part Blob
const parts = [
'Part 1: Header\n',
'---\n',
'Part 2: Body\n',
'---\n',
'Part 3: Footer',
];
const multiPartBlob = new Blob(parts, { type: 'text/plain' });
return {
textBlob,
jsonBlob,
htmlBlob,
csvBlob,
binaryBlob,
multiPartBlob,
};
}
// =============================================================================
// 2. Creating Files
// =============================================================================
/**
* Create File objects programmatically
*/
function createFiles() {
// Simple text file
const textFile = new File(['This is the file content'], 'document.txt', {
type: 'text/plain',
lastModified: Date.now(),
});
console.log('File properties:', {
name: textFile.name,
size: textFile.size,
type: textFile.type,
lastModified: new Date(textFile.lastModified).toISOString(),
});
// JSON file
const configData = {
version: '1.0.0',
settings: { theme: 'dark', language: 'en' },
};
const jsonFile = new File(
[JSON.stringify(configData, null, 2)],
'config.json',
{ type: 'application/json' }
);
// SVG file
const svgContent = `
<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">
<circle cx="50" cy="50" r="40" fill="blue"/>
</svg>
`;
const svgFile = new File([svgContent], 'circle.svg', {
type: 'image/svg+xml',
});
return { textFile, jsonFile, svgFile };
}
// =============================================================================
// 3. Reading Files with FileReader
// =============================================================================
/**
* FileReader wrapper with Promise
*/
class FileReaderAsync {
static readAsText(blob, encoding = 'UTF-8') {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result);
reader.onerror = () => reject(reader.error);
reader.readAsText(blob, encoding);
});
}
static readAsDataURL(blob) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result);
reader.onerror = () => reject(reader.error);
reader.readAsDataURL(blob);
});
}
static readAsArrayBuffer(blob) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result);
reader.onerror = () => reject(reader.error);
reader.readAsArrayBuffer(blob);
});
}
static readAsBinaryString(blob) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result);
reader.onerror = () => reject(reader.error);
reader.readAsBinaryString(blob);
});
}
static readWithProgress(blob, method, onProgress) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onprogress = (event) => {
if (event.lengthComputable && onProgress) {
onProgress({
loaded: event.loaded,
total: event.total,
percent: (event.loaded / event.total) * 100,
});
}
};
reader.onload = () => resolve(reader.result);
reader.onerror = () => reject(reader.error);
reader[method](blob);
});
}
}
// Usage example
async function readFileExamples() {
const textBlob = new Blob(['Hello, FileReader!'], { type: 'text/plain' });
// Read as text
const text = await FileReaderAsync.readAsText(textBlob);
console.log('Text:', text);
// Read as data URL
const dataUrl = await FileReaderAsync.readAsDataURL(textBlob);
console.log('Data URL:', dataUrl);
// Read as ArrayBuffer
const buffer = await FileReaderAsync.readAsArrayBuffer(textBlob);
console.log('ArrayBuffer:', buffer.byteLength, 'bytes');
// Modern alternative (blob.text(), blob.arrayBuffer())
const modernText = await textBlob.text();
const modernBuffer = await textBlob.arrayBuffer();
}
// =============================================================================
// 4. Blob URLs
// =============================================================================
/**
* Create and manage Blob URLs
*/
class BlobURLManager {
constructor() {
this.urls = new Set();
}
create(blob) {
const url = URL.createObjectURL(blob);
this.urls.add(url);
return url;
}
revoke(url) {
URL.revokeObjectURL(url);
this.urls.delete(url);
}
revokeAll() {
this.urls.forEach((url) => URL.revokeObjectURL(url));
this.urls.clear();
}
get count() {
return this.urls.size;
}
}
// Example: Create downloadable link
function createDownloadLink(blob, filename) {
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = filename;
link.textContent = `Download ${filename}`;
// Cleanup URL after download
link.onclick = () => {
setTimeout(() => URL.revokeObjectURL(url), 100);
};
return link;
}
// Example: Image preview
function createImagePreview(file) {
return new Promise((resolve, reject) => {
if (!file.type.startsWith('image/')) {
reject(new Error('Not an image file'));
return;
}
const url = URL.createObjectURL(file);
const img = new Image();
img.onload = () => {
URL.revokeObjectURL(url);
resolve(img);
};
img.onerror = () => {
URL.revokeObjectURL(url);
reject(new Error('Failed to load image'));
};
img.src = url;
});
}
// =============================================================================
// 5. Data Conversions
// =============================================================================
const DataConverter = {
// Blob conversions
async blobToText(blob) {
return blob.text();
},
textToBlob(text, type = 'text/plain') {
return new Blob([text], { type });
},
async blobToBase64(blob) {
return FileReaderAsync.readAsDataURL(blob);
},
base64ToBlob(base64, type = 'application/octet-stream') {
// Remove data URL prefix if present
const base64Data = base64.includes(',') ? base64.split(',')[1] : base64;
const binaryString = atob(base64Data);
const bytes = new Uint8Array(binaryString.length);
for (let i = 0; i < binaryString.length; i++) {
bytes[i] = binaryString.charCodeAt(i);
}
return new Blob([bytes], { type });
},
async blobToArrayBuffer(blob) {
return blob.arrayBuffer();
},
arrayBufferToBlob(buffer, type = 'application/octet-stream') {
return new Blob([buffer], { type });
},
// String conversions
stringToArrayBuffer(str) {
return new TextEncoder().encode(str).buffer;
},
arrayBufferToString(buffer) {
return new TextDecoder().decode(buffer);
},
// Hex conversions
arrayBufferToHex(buffer) {
return Array.from(new Uint8Array(buffer))
.map((b) => b.toString(16).padStart(2, '0'))
.join('');
},
hexToArrayBuffer(hex) {
const bytes = new Uint8Array(hex.length / 2);
for (let i = 0; i < hex.length; i += 2) {
bytes[i / 2] = parseInt(hex.substr(i, 2), 16);
}
return bytes.buffer;
},
};
// =============================================================================
// 6. Blob Slicing and Streaming
// =============================================================================
/**
* Read large files in chunks
*/
async function readInChunks(blob, chunkSize = 1024 * 1024, onChunk) {
let offset = 0;
let chunkIndex = 0;
while (offset < blob.size) {
const chunk = blob.slice(offset, offset + chunkSize);
const data = await chunk.arrayBuffer();
await onChunk({
index: chunkIndex,
data,
offset,
size: chunk.size,
isLast: offset + chunkSize >= blob.size,
});
offset += chunkSize;
chunkIndex++;
}
return chunkIndex;
}
/**
* Concatenate multiple Blobs
*/
function concatenateBlobs(blobs, type) {
return new Blob(blobs, { type: type || blobs[0]?.type });
}
/**
* Split Blob into equal parts
*/
function splitBlob(blob, numParts) {
const partSize = Math.ceil(blob.size / numParts);
const parts = [];
for (let i = 0; i < numParts; i++) {
const start = i * partSize;
const end = Math.min(start + partSize, blob.size);
parts.push(blob.slice(start, end));
}
return parts;
}
// =============================================================================
// 7. File Downloads
// =============================================================================
const FileDownloader = {
/**
* Download content as a file
*/
download(content, filename, type = 'text/plain') {
const blob = new Blob([content], { type });
this.downloadBlob(blob, filename);
},
/**
* Download Blob as file
*/
downloadBlob(blob, filename) {
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = filename;
a.style.display = 'none';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
},
/**
* Download JSON data
*/
downloadJSON(data, filename) {
const json = JSON.stringify(data, null, 2);
this.download(json, filename, 'application/json');
},
/**
* Download CSV data
*/
downloadCSV(rows, filename, headers) {
let csv = '';
if (headers) {
csv += headers.join(',') + '\n';
}
rows.forEach((row) => {
csv +=
row
.map((cell) => {
// Escape quotes and wrap in quotes if needed
if (
typeof cell === 'string' &&
(cell.includes(',') || cell.includes('"'))
) {
return `"${cell.replace(/"/g, '""')}"`;
}
return cell;
})
.join(',') + '\n';
});
this.download(csv, filename, 'text/csv');
},
/**
* Download from URL
*/
async downloadFromURL(url, filename) {
const response = await fetch(url);
const blob = await response.blob();
this.downloadBlob(blob, filename);
},
};
// =============================================================================
// 8. File Uploads
// =============================================================================
const FileUploader = {
/**
* Upload file with FormData
*/
async upload(file, url, additionalData = {}) {
const formData = new FormData();
formData.append('file', file);
Object.entries(additionalData).forEach(([key, value]) => {
formData.append(key, value);
});
const response = await fetch(url, {
method: 'POST',
body: formData,
});
if (!response.ok) {
throw new Error(`Upload failed: ${response.statusText}`);
}
return response.json();
},
/**
* Upload with progress tracking
*/
uploadWithProgress(file, url, onProgress) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
const formData = new FormData();
formData.append('file', file);
xhr.upload.addEventListener('progress', (e) => {
if (e.lengthComputable) {
onProgress({
loaded: e.loaded,
total: e.total,
percent: (e.loaded / e.total) * 100,
});
}
});
xhr.addEventListener('load', () => {
if (xhr.status >= 200 && xhr.status < 300) {
resolve(JSON.parse(xhr.responseText));
} else {
reject(new Error(`Upload failed: ${xhr.statusText}`));
}
});
xhr.addEventListener('error', () => reject(new Error('Upload failed')));
xhr.addEventListener('abort', () => reject(new Error('Upload aborted')));
xhr.open('POST', url);
xhr.send(formData);
});
},
/**
* Upload multiple files
*/
async uploadMultiple(files, url, onProgress) {
const results = [];
let completed = 0;
for (const file of files) {
const result = await this.upload(file, url);
results.push(result);
completed++;
if (onProgress) {
onProgress({
completed,
total: files.length,
percent: (completed / files.length) * 100,
});
}
}
return results;
},
/**
* Upload in chunks
*/
async uploadChunked(file, url, chunkSize = 1024 * 1024, onProgress) {
const totalChunks = Math.ceil(file.size / chunkSize);
const uploadId = Date.now().toString(36);
for (let i = 0; i < totalChunks; i++) {
const start = i * chunkSize;
const end = Math.min(start + chunkSize, file.size);
const chunk = file.slice(start, end);
const formData = new FormData();
formData.append('chunk', chunk);
formData.append('chunkIndex', i.toString());
formData.append('totalChunks', totalChunks.toString());
formData.append('uploadId', uploadId);
formData.append('fileName', file.name);
await fetch(url, {
method: 'POST',
body: formData,
});
if (onProgress) {
onProgress({
chunk: i + 1,
totalChunks,
percent: ((i + 1) / totalChunks) * 100,
});
}
}
return uploadId;
},
};
// =============================================================================
// 9. Image Processing
// =============================================================================
const ImageProcessor = {
/**
* Load image from File/Blob
*/
async loadImage(fileOrBlob) {
return new Promise((resolve, reject) => {
const url = URL.createObjectURL(fileOrBlob);
const img = new Image();
img.onload = () => {
URL.revokeObjectURL(url);
resolve(img);
};
img.onerror = () => {
URL.revokeObjectURL(url);
reject(new Error('Failed to load image'));
};
img.src = url;
});
},
/**
* Resize image
*/
async resize(file, maxWidth, maxHeight, quality = 0.9) {
const img = await this.loadImage(file);
let { width, height } = img;
// Calculate new dimensions
if (width > maxWidth) {
height = (height * maxWidth) / width;
width = maxWidth;
}
if (height > maxHeight) {
width = (width * maxHeight) / height;
height = maxHeight;
}
// Draw to canvas
const canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0, width, height);
// Convert to Blob
return new Promise((resolve) => {
canvas.toBlob(resolve, file.type, quality);
});
},
/**
* Crop image
*/
async crop(file, x, y, width, height) {
const img = await this.loadImage(file);
const canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext('2d');
ctx.drawImage(img, x, y, width, height, 0, 0, width, height);
return new Promise((resolve) => {
canvas.toBlob(resolve, file.type);
});
},
/**
* Convert format
*/
async convertFormat(file, targetType, quality = 0.9) {
const img = await this.loadImage(file);
const canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0);
return new Promise((resolve) => {
canvas.toBlob(resolve, targetType, quality);
});
},
/**
* Get image dimensions
*/
async getDimensions(file) {
const img = await this.loadImage(file);
return { width: img.width, height: img.height };
},
/**
* Create thumbnail
*/
async createThumbnail(file, size = 150) {
return this.resize(file, size, size, 0.8);
},
};
// =============================================================================
// 10. File Type Detection
// =============================================================================
const FileTypeDetector = {
// File signatures (magic numbers)
signatures: {
'image/jpeg': [0xff, 0xd8, 0xff],
'image/png': [0x89, 0x50, 0x4e, 0x47],
'image/gif': [0x47, 0x49, 0x46],
'image/webp': [0x52, 0x49, 0x46, 0x46],
'application/pdf': [0x25, 0x50, 0x44, 0x46],
'application/zip': [0x50, 0x4b, 0x03, 0x04],
'video/mp4': [0x00, 0x00, 0x00], // ftyp check needed
'audio/mpeg': [0x49, 0x44, 0x33], // ID3
},
/**
* Detect type by magic bytes
*/
async detectByBytes(file) {
const header = file.slice(0, 12);
const buffer = await header.arrayBuffer();
const bytes = new Uint8Array(buffer);
for (const [type, signature] of Object.entries(this.signatures)) {
if (this.matchSignature(bytes, signature)) {
return type;
}
}
return file.type || 'application/octet-stream';
},
matchSignature(bytes, signature) {
for (let i = 0; i < signature.length; i++) {
if (bytes[i] !== signature[i]) {
return false;
}
}
return true;
},
/**
* Get type by extension
*/
getTypeByExtension(filename) {
const ext = filename.split('.').pop().toLowerCase();
const types = {
// Images
jpg: 'image/jpeg',
jpeg: 'image/jpeg',
png: 'image/png',
gif: 'image/gif',
webp: 'image/webp',
svg: 'image/svg+xml',
// Documents
pdf: 'application/pdf',
doc: 'application/msword',
docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
// Data
json: 'application/json',
xml: 'application/xml',
csv: 'text/csv',
txt: 'text/plain',
// Code
html: 'text/html',
css: 'text/css',
js: 'application/javascript',
// Archives
zip: 'application/zip',
rar: 'application/x-rar-compressed',
// Audio/Video
mp3: 'audio/mpeg',
mp4: 'video/mp4',
wav: 'audio/wav',
};
return types[ext] || 'application/octet-stream';
},
/**
* Validate file type
*/
async validate(file, allowedTypes) {
const detectedType = await this.detectByBytes(file);
return allowedTypes.some((type) => {
if (type.endsWith('/*')) {
return detectedType.startsWith(type.slice(0, -1));
}
return detectedType === type;
});
},
};
// =============================================================================
// Export
// =============================================================================
if (typeof module !== 'undefined' && module.exports) {
module.exports = {
createBlobs,
createFiles,
FileReaderAsync,
BlobURLManager,
DataConverter,
readInChunks,
concatenateBlobs,
splitBlob,
FileDownloader,
FileUploader,
ImageProcessor,
FileTypeDetector,
};
}