0
# File and Blob Operations
1
2
Integration with file system and blob operations for uploading files and handling binary data. node-fetch re-exports classes and utilities from the fetch-blob package for comprehensive file handling.
3
4
## Capabilities
5
6
### Blob Class
7
8
Web-compatible Blob implementation for handling binary data with MIME type support.
9
10
```javascript { .api }
11
/**
12
* Blob implementation for binary data handling
13
*/
14
class Blob {
15
constructor(blobParts?: BlobPart[], options?: BlobPropertyBag);
16
17
readonly size: number;
18
readonly type: string;
19
20
arrayBuffer(): Promise<ArrayBuffer>;
21
stream(): ReadableStream<Uint8Array>;
22
text(): Promise<string>;
23
slice(start?: number, end?: number, contentType?: string): Blob;
24
}
25
26
interface BlobPropertyBag {
27
type?: string;
28
endings?: 'transparent' | 'native';
29
}
30
31
type BlobPart = string | ArrayBuffer | ArrayBufferView | Blob;
32
```
33
34
**Usage Examples:**
35
36
```javascript
37
import { Blob } from 'node-fetch';
38
39
// Create blob from string
40
const textBlob = new Blob(['Hello, World!'], { type: 'text/plain' });
41
console.log('Size:', textBlob.size); // 13
42
console.log('Type:', textBlob.type); // 'text/plain'
43
44
// Create blob from binary data
45
const binaryData = new Uint8Array([0x48, 0x65, 0x6c, 0x6c, 0x6f]); // "Hello"
46
const binaryBlob = new Blob([binaryData], { type: 'application/octet-stream' });
47
48
// Create blob from multiple parts
49
const multipartBlob = new Blob([
50
'Data: ',
51
binaryData,
52
'\nEnd of data'
53
], { type: 'text/plain' });
54
55
// Read blob content
56
const text = await textBlob.text();
57
console.log(text); // 'Hello, World!'
58
59
const buffer = await textBlob.arrayBuffer();
60
console.log(new Uint8Array(buffer)); // [72, 101, 108, 108, 111, 44, 32, 87, 111, 114, 108, 100, 33]
61
```
62
63
### File Class
64
65
Extended Blob class with file metadata like name and modification time.
66
67
```javascript { .api }
68
/**
69
* File implementation extending Blob with file metadata
70
*/
71
class File extends Blob {
72
constructor(fileBits: BlobPart[], fileName: string, options?: FilePropertyBag);
73
74
readonly name: string;
75
readonly lastModified: number;
76
readonly webkitRelativePath: string;
77
}
78
79
interface FilePropertyBag extends BlobPropertyBag {
80
lastModified?: number;
81
}
82
```
83
84
**Usage Examples:**
85
86
```javascript
87
import { File } from 'node-fetch';
88
89
// Create file from string content
90
const textFile = new File(['File content'], 'example.txt', {
91
type: 'text/plain',
92
lastModified: Date.now()
93
});
94
95
console.log('Name:', textFile.name); // 'example.txt'
96
console.log('Size:', textFile.size); // 12
97
console.log('Type:', textFile.type); // 'text/plain'
98
console.log('Modified:', textFile.lastModified);
99
100
// Create JSON file
101
const jsonData = { name: 'Alice', age: 30 };
102
const jsonFile = new File([JSON.stringify(jsonData)], 'data.json', {
103
type: 'application/json'
104
});
105
106
// Use with FormData for file uploads
107
const formData = new FormData();
108
formData.append('upload', textFile);
109
formData.append('metadata', jsonFile);
110
111
const response = await fetch('https://httpbin.org/post', {
112
method: 'POST',
113
body: formData
114
});
115
```
116
117
### File System Integration
118
119
Utilities for creating Blob and File objects from file system paths.
120
121
```javascript { .api }
122
/**
123
* Create File from file system path (async)
124
* @param path - File system path
125
* @param type - MIME type (optional, auto-detected if not provided)
126
* @returns Promise resolving to File object
127
*/
128
function fileFrom(path: string, type?: string): Promise<File>;
129
130
/**
131
* Create File from file system path (sync)
132
* @param path - File system path
133
* @param type - MIME type (optional, auto-detected if not provided)
134
* @returns File object
135
*/
136
function fileFromSync(path: string, type?: string): File;
137
138
/**
139
* Create Blob from file system path (async)
140
* @param path - File system path
141
* @param type - MIME type (optional, auto-detected if not provided)
142
* @returns Promise resolving to Blob object
143
*/
144
function blobFrom(path: string, type?: string): Promise<Blob>;
145
146
/**
147
* Create Blob from file system path (sync)
148
* @param path - File system path
149
* @param type - MIME type (optional, auto-detected if not provided)
150
* @returns Blob object
151
*/
152
function blobFromSync(path: string, type?: string): Blob;
153
```
154
155
**Usage Examples:**
156
157
```javascript
158
import { fileFrom, fileFromSync, blobFrom, blobFromSync } from 'node-fetch';
159
160
// Async file loading
161
const imageFile = await fileFrom('./image.jpg', 'image/jpeg');
162
console.log('File name:', imageFile.name); // 'image.jpg'
163
console.log('File size:', imageFile.size); // File size in bytes
164
console.log('File type:', imageFile.type); // 'image/jpeg'
165
166
// Sync file loading
167
const textFile = fileFromSync('./document.txt', 'text/plain');
168
169
// Auto-detect MIME type
170
const autoFile = await fileFrom('./data.json'); // Type will be 'application/json'
171
172
// Create blob from file
173
const documentBlob = await blobFrom('./document.pdf');
174
console.log('Blob type:', documentBlob.type); // 'application/pdf'
175
176
// Use with fetch for file uploads
177
const uploadFile = await fileFrom('./upload.png', 'image/png');
178
179
const formData = new FormData();
180
formData.append('file', uploadFile);
181
182
const response = await fetch('https://httpbin.org/post', {
183
method: 'POST',
184
body: formData
185
});
186
```
187
188
### FormData Integration
189
190
Using File and Blob objects with FormData for multipart uploads.
191
192
```javascript { .api }
193
/**
194
* FormData class for multipart/form-data requests
195
*/
196
class FormData {
197
append(name: string, value: string | Blob | File, filename?: string): void;
198
delete(name: string): void;
199
get(name: string): FormDataEntryValue | null;
200
getAll(name: string): FormDataEntryValue[];
201
has(name: string): boolean;
202
set(name: string, value: string | Blob | File, filename?: string): void;
203
forEach(callback: (value: FormDataEntryValue, key: string, parent: FormData) => void): void;
204
entries(): IterableIterator<[string, FormDataEntryValue]>;
205
keys(): IterableIterator<string>;
206
values(): IterableIterator<FormDataEntryValue>;
207
}
208
209
type FormDataEntryValue = string | File;
210
```
211
212
**Usage Examples:**
213
214
```javascript
215
import { FormData, fileFrom } from 'node-fetch';
216
217
// Create form with file uploads
218
const formData = new FormData();
219
220
// Add text fields
221
formData.append('username', 'alice');
222
formData.append('description', 'Profile update');
223
224
// Add file from file system
225
const avatarFile = await fileFrom('./avatar.jpg', 'image/jpeg');
226
formData.append('avatar', avatarFile);
227
228
// Add file created in memory
229
const jsonFile = new File([JSON.stringify({ key: 'value' })], 'config.json', {
230
type: 'application/json'
231
});
232
formData.append('config', jsonFile);
233
234
// Add blob data
235
const binaryBlob = new Blob([new Uint8Array([1, 2, 3, 4])], {
236
type: 'application/octet-stream'
237
});
238
formData.append('data', binaryBlob, 'binary-data.bin');
239
240
// Upload form data
241
const response = await fetch('https://httpbin.org/post', {
242
method: 'POST',
243
body: formData
244
// Content-Type header is set automatically with boundary
245
});
246
247
const result = await response.json();
248
console.log('Files uploaded:', Object.keys(result.files));
249
```
250
251
### Stream Integration
252
253
Working with streams for efficient file processing and uploads.
254
255
```javascript { .api }
256
interface StreamOperations {
257
stream(): ReadableStream<Uint8Array>;
258
arrayBuffer(): Promise<ArrayBuffer>;
259
}
260
```
261
262
**Usage Examples:**
263
264
```javascript
265
import { createReadStream } from 'fs';
266
import { pipeline } from 'stream/promises';
267
268
// Stream file upload
269
const fileStream = createReadStream('./large-file.zip');
270
271
const response = await fetch('https://httpbin.org/post', {
272
method: 'POST',
273
body: fileStream,
274
headers: {
275
'Content-Type': 'application/zip'
276
}
277
});
278
279
// Process blob as stream
280
const imageBlob = await blobFrom('./image.jpg');
281
const stream = imageBlob.stream();
282
283
// Transform stream data
284
const reader = stream.getReader();
285
const chunks = [];
286
287
while (true) {
288
const { done, value } = await reader.read();
289
if (done) break;
290
291
chunks.push(value);
292
console.log('Read chunk:', value.length, 'bytes');
293
}
294
295
const totalData = new Uint8Array(chunks.reduce((acc, chunk) => acc + chunk.length, 0));
296
let offset = 0;
297
for (const chunk of chunks) {
298
totalData.set(chunk, offset);
299
offset += chunk.length;
300
}
301
302
// Use with pipeline for efficient processing
303
const sourceBlob = await blobFrom('./input.txt');
304
const destinationStream = createWriteStream('./output.txt');
305
306
await pipeline(sourceBlob.stream(), destinationStream);
307
console.log('File copied successfully');
308
```
309
310
### File Upload Patterns
311
312
Common patterns for uploading files with progress tracking and error handling.
313
314
```javascript { .api }
315
interface FileUploadPattern {
316
uploadSingleFile(file: File, url: string): Promise<Response>;
317
uploadMultipleFiles(files: File[], url: string): Promise<Response>;
318
uploadWithProgress(file: File, url: string, onProgress: (progress: number) => void): Promise<Response>;
319
}
320
```
321
322
**Usage Examples:**
323
324
```javascript
325
// Single file upload
326
async function uploadFile(filePath, uploadUrl) {
327
const file = await fileFrom(filePath);
328
329
const formData = new FormData();
330
formData.append('file', file);
331
332
const response = await fetch(uploadUrl, {
333
method: 'POST',
334
body: formData
335
});
336
337
if (!response.ok) {
338
throw new Error(`Upload failed: ${response.status} ${response.statusText}`);
339
}
340
341
return await response.json();
342
}
343
344
// Multiple file upload
345
async function uploadFiles(filePaths, uploadUrl) {
346
const formData = new FormData();
347
348
for (let i = 0; i < filePaths.length; i++) {
349
const file = await fileFrom(filePaths[i]);
350
formData.append(`file${i}`, file);
351
}
352
353
return await fetch(uploadUrl, {
354
method: 'POST',
355
body: formData
356
});
357
}
358
359
// File upload with custom metadata
360
async function uploadWithMetadata(filePath, metadata, uploadUrl) {
361
const file = await fileFrom(filePath);
362
363
const formData = new FormData();
364
formData.append('file', file);
365
formData.append('metadata', JSON.stringify(metadata));
366
formData.append('timestamp', new Date().toISOString());
367
368
return await fetch(uploadUrl, {
369
method: 'POST',
370
body: formData
371
});
372
}
373
374
// Usage examples
375
try {
376
// Upload single file
377
const result = await uploadFile('./document.pdf', 'https://api.example.com/upload');
378
console.log('Upload successful:', result);
379
380
// Upload multiple files
381
const multiResult = await uploadFiles([
382
'./image1.jpg',
383
'./image2.png',
384
'./document.txt'
385
], 'https://api.example.com/upload/batch');
386
387
// Upload with metadata
388
const metaResult = await uploadWithMetadata('./data.csv', {
389
category: 'reports',
390
department: 'sales',
391
confidential: false
392
}, 'https://api.example.com/upload/data');
393
394
} catch (error) {
395
console.error('Upload failed:', error.message);
396
}
397
```
398
399
### Binary Data Handling
400
401
Advanced patterns for working with binary data and custom file formats.
402
403
```javascript { .api }
404
interface BinaryDataHandling {
405
processBinaryFile(path: string): Promise<ProcessedData>;
406
createCustomFile(data: Uint8Array, metadata: FileMetadata): File;
407
validateFileFormat(file: File): Promise<boolean>;
408
}
409
```
410
411
**Usage Examples:**
412
413
```javascript
414
// Process binary file with custom format
415
async function processBinaryFile(filePath) {
416
const blob = await blobFrom(filePath);
417
const buffer = await blob.arrayBuffer();
418
const data = new Uint8Array(buffer);
419
420
// Example: Read custom header (first 16 bytes)
421
const header = data.slice(0, 16);
422
const magic = new TextDecoder().decode(header.slice(0, 4));
423
424
if (magic !== 'MYMT') { // Custom magic bytes
425
throw new Error('Invalid file format');
426
}
427
428
const version = data[4];
429
const flags = data[5];
430
const dataLength = new DataView(buffer).getUint32(6, true); // Little endian
431
432
return {
433
magic,
434
version,
435
flags,
436
dataLength,
437
data: data.slice(16) // Actual data starts after header
438
};
439
}
440
441
// Create custom binary file
442
function createBinaryFile(content, filename) {
443
// Create header
444
const header = new Uint8Array(16);
445
const encoder = new TextEncoder();
446
447
// Magic bytes
448
header.set(encoder.encode('MYMT'), 0);
449
450
// Version and flags
451
header[4] = 1; // Version
452
header[5] = 0; // Flags
453
454
// Data length (little endian)
455
const view = new DataView(header.buffer);
456
view.setUint32(6, content.length, true);
457
458
// Combine header and content
459
const fileData = new Uint8Array(header.length + content.length);
460
fileData.set(header, 0);
461
fileData.set(content, header.length);
462
463
return new File([fileData], filename, {
464
type: 'application/octet-stream'
465
});
466
}
467
468
// Validate file format
469
async function validateImageFile(file) {
470
if (!file.type.startsWith('image/')) {
471
return false;
472
}
473
474
const buffer = await file.arrayBuffer();
475
const data = new Uint8Array(buffer);
476
477
// Check for common image format signatures
478
if (data.length < 4) return false;
479
480
// JPEG
481
if (data[0] === 0xFF && data[1] === 0xD8 && data[2] === 0xFF) {
482
return true;
483
}
484
485
// PNG
486
if (data[0] === 0x89 && data[1] === 0x50 && data[2] === 0x4E && data[3] === 0x47) {
487
return true;
488
}
489
490
// GIF
491
if ((data[0] === 0x47 && data[1] === 0x49 && data[2] === 0x46) &&
492
(data[3] === 0x38 && (data[4] === 0x37 || data[4] === 0x39))) {
493
return true;
494
}
495
496
return false;
497
}
498
499
// Usage
500
const customFile = createBinaryFile(
501
new TextEncoder().encode('Hello, World!'),
502
'custom-data.bin'
503
);
504
505
const isValid = await validateImageFile(await fileFrom('./image.jpg'));
506
console.log('Valid image:', isValid);
507
```