Modern replacement of file-saver.js.
npm install tinysaveryarn add tinysaverpnpm add tinysaverimport {
saveAs,
saveAsAsync,
saveText,
saveJSON,
saveCanvas,
saveStream,
} from 'tinysaver'
// Save a Blob
saveAs(new Blob(['hello world'], { type: 'text/plain' }), 'hello-world.txt')
// Save text content
saveText('Hello World', 'greeting.txt')
// Save JSON data
saveJSON({ name: 'John', age: 30 }, 'data.json', { space: 2 })
// Save canvas as image
const canvas = document.querySelector('canvas')
saveCanvas(canvas, 'image.png', { quality: 0.95 })
// Promise-based save
await saveAsAsync(new Blob(['hello async']), 'async.txt')
// Save from stream/response
const response = await fetch('/api/export')
await saveStream(response, 'export.bin')import { saveAs } from 'tinysaver'
saveAs(new Blob(['hello world'], { type: 'text/plain' }), 'hello-world.txt', {
autoBom: true, // Add UTF-8 BOM for text files
clickDelay: 100, // Delay before triggering download
openInNewTab: false, // Open in new tab instead of downloading
disableClick: false, // Disable automatic click simulation
onStart() {
console.log('Download started')
},
onComplete() {
console.log('Download completed')
},
onError(err) {
console.error('Download failed', err)
},
onProgress(loaded, total) {
console.log(`${loaded}/${total}`)
},
timeout: 10_000, // Abort automatically after 10s
signal: abortController.signal, // Manual cancellation
fetchOptions: { credentials: 'include' }, // For CORS probing request
preferFileSystemAccess: true, // Use showSaveFilePicker when supported
onPhaseChange(phase) {
console.log(phase) // probing/downloading/saving/completed/error/aborted
},
})All download methods support lifecycle callbacks:
saveText('content', 'file.txt', {
onStart() {
// Called when download process starts
},
onProgress(loaded, total) {
// Called during download progress
console.log(`Downloaded ${loaded}/${total} bytes`)
},
onComplete() {
// Called when download completes
},
onError(error) {
// Called when download fails
console.error(error)
},
})tinysaver supports all modern browsers with automatic fallback for older versions:
- β Chrome/Edge (all versions with download attribute support)
- β Firefox (all versions)
- β Safari (all versions, including iOS)
- β Opera (all versions)
β οΈ IE (fallback via msSaveOrOpenBlob)
Save any Blob or URL as a file. Compatible with FileSaver.js saveAs API.
Promise-based version of saveAs, suitable for async workflows and explicit error handling.
Parameters:
blob- Blob object or URL stringfilename- Name of the file to save (optional)options- Download options (optional)
Save text content as a file.
Parameters:
text- Text content to savefilename- Name of the text fileoptions- Download options with optionalmimeTypeproperty
Save JSON data as a file.
Parameters:
data- JavaScript object or value to savefilename- Name of the JSON fileoptions- Download options with optionalspaceproperty for formatting
Save HTML canvas as an image file.
Parameters:
canvas- HTMLCanvasElement to savefilename- Name of the image fileoptions- Download options with optionaltypeandqualityproperties
Save stream data (ReadableStream, Response, AsyncIterable) as a file.
The library includes comprehensive unit tests covering:
- π BrowserDetector static and instance methods
- π₯ FileDownloader core functionality and error handling
- π·οΈ BOM (Byte Order Mark) insertion for text files
- π Default filename handling
- πΎ saveText, saveJSON, and saveCanvas implementations
β οΈ Canvas conversion error handling- π Callback invocation during download lifecycle
- β±οΈ Timeout/abort behavior and phase callbacks
- π Stream-based save flow
- π File System Access API preferred path
- Unit tests run in
jsdomfor deterministic behavior. - Runtime fallback matrix is covered by branches for download attribute,
msSaveOrOpenBlob, andFileReader. - Recommended release validation targets:
- Desktop: latest Chrome, Firefox, Safari
- Mobile: iOS Safari / Chrome iOS WebView
- Legacy fallback: environments exposing
msSaveOrOpenBlob
Run tests with:
pnpm test