Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

17 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ’Ύ tinysaver

CI NPM VERSION NPM DOWNLOADS LICENSE

Modern replacement of file-saver.js.

πŸ“¦ Install

npm install tinysaver
yarn add tinysaver
pnpm add tinysaver

πŸš€ Usage

✨ Basic Usage

import { saveAs, saveAsAsync, saveText, saveJSON, saveCanvas } from 'tinysaver'
import { saveStream } from 'tinysaver/stream'

// 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')

🌊 Stream Entry

Stream support is published from a separate entry so applications that only use Blob, URL, text, JSON, or canvas downloads do not bundle the stream implementation.

import {
  saveStream,
  StreamDownloader,
  type DownloadStreamSource,
  type SaveStreamOptions,
} from 'tinysaver/stream'

await saveStream(await fetch('/api/export'), 'export.bin')

const downloader = new StreamDownloader()
await downloader.saveStream(source, 'export.bin', options)

saveStream is not exported from tinysaver, and FileDownloader no longer has a saveStream method. Migrate root imports and class usage as follows:

// Before
import { FileDownloader, saveStream } from 'tinysaver'

// After
import { saveStream, StreamDownloader } from 'tinysaver/stream'

βš™οΈ With Options

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}`) // total is 0 when size is unknown
  },
  timeout: 10_000, // Abort automatically after 10s
  signal: abortController.signal, // Manual cancellation
  fetchOptions: { credentials: 'include' }, // For CORS probing request
  preferFileSystemAccess: true, // Use showSaveFilePicker for Blob/stream sources
  onPhaseChange(phase) {
    console.log(phase) // probing/downloading/saving/completed/error/aborted
  },
})

πŸ‘ Callbacks

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)
  },
})

🌐 Browser Support

tinysaver targets the following browser versions and newer:

  • Chrome 87
  • Edge 88
  • Firefox 78
  • Safari 14

Internet Explorer is not supported.

πŸ“š API

πŸ’Ύ saveAs(blob, filename?, options?)

Save any Blob or URL as a file. Compatible with FileSaver.js saveAs API.

⏳ saveAsAsync(blob, filename?, options?)

Promise-based version of saveAs, suitable for async workflows and explicit error handling.

Parameters:

  • blob - Blob object or URL string
  • filename - Name of the file to save (optional)
  • options - Download options (optional)

πŸ“ saveText(text, filename, options?)

Save text content as a file.

Parameters:

  • text - Text content to save
  • filename - Name of the text file
  • options - Download options with optional mimeType property

πŸ“„ saveJSON(data, filename, options?)

Save JSON data as a file.

Parameters:

  • data - JavaScript object or value to save
  • filename - Name of the JSON file
  • options - Download options with optional space property for formatting

🎨 saveCanvas(canvas, filename, options?)

Save HTML canvas as an image file.

Parameters:

  • canvas - HTMLCanvasElement to save
  • filename - Name of the image file
  • options - Download options with optional type and quality properties

🌊 saveStream(source, filename, options?)

Save stream data (ReadableStream, Response, AsyncIterable) as a file. Import it from tinysaver/stream.

When preferFileSystemAccess is enabled and supported, chunks are written directly to the selected file. Other browsers materialize the stream as a browser-managed Blob before starting the download. Abort signals and timeouts cancel the active stream and propagate cancellation to its source.

Blob fallback buffering is limited to 256 MiB by default to protect the browser from unbounded memory growth. Set maxBufferBytes to a positive byte limit when another bound is appropriate for the application.

URL sources always use the browser download transport. File pickers require a transient user gesture and therefore cannot be opened after an asynchronous URL probe or transfer.

βœ… Testing

The library includes comprehensive unit tests covering:

  • πŸ“₯ 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

Compatibility Matrix

  • Unit tests run in jsdom for deterministic behavior.
  • Browser tests run in Chromium, Firefox, and WebKit through Playwright.
  • Production builds target Chrome 87, Edge 88, Firefox 78, and Safari 14.
  • Downloads use the standard anchor download attribute and URL API.
  • IE-only and pre-modern browser fallbacks are intentionally excluded.

Run tests with:

pnpm test
pnpm test:browser

πŸ§ͺ Playground

The Vue playground contains interactive examples for saving text, JSON, canvas artwork, and generated streams directly in the browser.

pnpm playground

Run pnpm playground:build to verify its production bundle.

πŸ™ Credits

πŸ“„ License

MIT License Β© 2025-PRESENT ntnyq

About

πŸ“¦ Modern replacement of FileSaver.js.

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages