file_saver 0.5.0 copy "file_saver: ^0.5.0" to clipboard
file_saver: ^0.5.0 copied to clipboard

Save files from bytes, paths, streams, and URLs across Android, iOS, Web, Windows, macOS, and Linux.

Changelog #

All notable changes to this project will be documented in this file.

0.5.0 #

  • Breaking: replaced the dio dependency with package:http.
    • dioClient is now httpClient (http.Client?) on saveFile, saveAs and saveLinkAsStream.
    • transformDioResponse is removed; responses are always bytes. Fetch and transform yourself, then pass bytes:.
    • LinkDetails.responseType is removed. LinkDetails.uri exposes the link with queryParameters merged.
    • HTTP 4xx/5xx responses now throw http.ClientException instead of writing the error body to disk.
    • Fixes #102.
  • macOS: sandbox failures now say which entitlement is missing — com.apple.security.files.downloads.read-write when the Downloads write fails, com.apple.security.network.client when the download fails.
  • Migrated Android to built-in Kotlin / AGP 9 compatibility. Requires Flutter 3.44+.
  • Added initialDirectory to saveAs, saveAsStream and saveLinkAsStream so the save dialog can open in a chosen folder (macOS, Windows, iOS, Android).
  • Added saveToGallery for saving images and videos to the photo library — MediaStore on Android, Photos on iOS — with an optional album.
  • Added dialogTitle to saveAs, saveAsStream and saveLinkAsStream (macOS, Windows).
  • Windows saveAs converts initialDirectory and dialogTitle from UTF-8 with MultiByteToWideChar.
  • Breaking: Android saveFile now throws a PlatformException on failure instead of returning an error message as the path.
  • Threading and streaming hardening across platforms:
    • Android: file copies run on a supervised IO scope and reply exactly once; saveAs survives rotation while the picker is open, fails cleanly when the Activity is destroyed or no app can show the picker, and rejects a second saveAs while one is open instead of silently dropping the first. Error details no longer carry a Throwable the channel codec cannot encode.
    • iOS: temp-file writes and copies run off the main thread, payloads are no longer copied into [UInt8], the picker is presented on the top-most controller, and a second saveAs while one is open is rejected.
    • macOS: copies stream in 1 MiB chunks off the main thread and failures throw instead of returning "Failed to save file" as the path.
    • Windows: the dialog is owned by the app window, uses heap buffers instead of a 1 MiB stack array and fixed MAX_PATH statics (a long file name aborted the process), builds the filter correctly, converts names and paths from UTF-8, and reports dialog errors instead of treating them as cancel.
    • Web: cancelling the File System Access picker resolves to null like other platforms; a failed stream is aborted without masking the original error.
    • saveAsStream deletes its temp file when the stream fails.
  • Platform channels are now generated with Pigeon from pigeons/messages.dart (regenerate with tool/pigeon.sh), so argument mismatches fail at compile time. Windows saveAs returns the path as a UTF-8 string. macOS deployment target is now 10.15.
  • Removed the unused FileUtils.kt and the duplicate macos/Classes sources — macOS builds from macos/file_saver/Sources for both CocoaPods and Swift Package Manager.
  • Documented macOS entitlement file naming and Windows SDK requirements.

0.4.0 #

  • Added Swift Package Manager support for iOS and macOS.
  • Split native file helpers behind conditional imports to keep Web/Wasm analysis away from dart:io and platform-specific path provider implementations.
  • Hardened Android file name handling against path traversal.
  • Moved Android saveAs file writes off the main thread and avoids resolving SAF document paths after saving.
  • Added web saveAs support using the existing browser download flow.
  • Added downloadLink for web browser handoff and Android DownloadManager downloads without loading bytes into Dart memory.
  • Added saveAsStream for native streamed writes via a temporary file.
  • Added saveLinkAsStream for authenticated streamed URL downloads with request headers where supported.
  • Added native file-path copying for iOS, macOS, and Windows saveAs to avoid loading filePath inputs into memory.
  • Made saveAs fileExtension optional.
  • Fixed macOS saveAs cancellation so the platform call always completes.
  • Added Windows invalid file name validation for saveAs.
  • Updated Android Gradle, Kotlin, JVM, and SDK settings for current Flutter support.

0.3.1 #

  • Added includeExtension boolean parameter to control whether file extension should be included in the saved filename
  • Renamed parameter from ext to fileExtension for better clarity and consistency
  • Added new MIME types: AVIF, HEIC, HEIF, Markdown, SQL, SVG, WebM, WebP, XML, YAML
  • Bug fixes and performance improvements
  • Updated dependencies to latest compatible versions
  • Enhanced platform compatibility and stability

0.3.0 #

  • Fixed and added saveAs for windows

0.2.14 #

  • Merged PR #117 to update conditional imports for web (wasm)
  • Merged PR #121 added dynamic access to enum for whoever need it,
    MimeType.get('pdf');
    
  • Merged PR #123 for upgrade to web 1.0.0

0.2.13 #

  • Merge PR #115 for wasm build
  • Added 3 MP4 mime types for better compatibility with the MP4 files

0.2.12 #

  • Minor network related bug fixes, fixing issue #105
  • & Issue #106

0.2.11 #

  • Merged PR #87 for backward compatibility with the older versions of java

0.2.10 #

  • Moved from http to dio for better control over the headers and other options
  • LinkDetails has more options such as method & body
    here is the example of how to use the LinkDetails
     LinkDetails(
         link: "www.example.com/file.extention",
         headers: /// Your headers here,
         method: /// Your method here (GET, POST, PUT, DELETE, PATCH),
         body: /// Request body here
     ),
    
  • Both saveFile and saveAs methods now have the dioClient & transformDioResponse as a parameter, so you can pass your own dio client to the method and it will use that client to download the file & you can also pass the transformDioResponse to transform the response as per your requirement.\
    await FileSaver.instance.saveFile(
                      name: "FileName",
                      link: "www.example.com/file.extention", 
                      filePath: "pathOfFile",
                      file: File(),
                      bytes: bytes,
                      ext: "extention",
                      mimeType: MimeType.pdf,
                      dioClient: Dio(),
                      transformDioResponse: (response) {
                        return response.data;
                      });
    
  • Fixed (GitHub issue #95)
  • Fixed (GitHub issue #92)

0.2.9 #

  • Merged PR #75 resolving issue [#75][https://github.com/incrediblezayed/file_saver/issues/75]
  • Merged PR #79 resolving issue #78
  • Merged PR #74 resolving issue #73
  • Merged PR #77 for better README.md

0.2.8 #

  • Moving saveAs() support for macOS to production.

0.2.7 #

  • Updated the http package to the latest version (issue #63)

0.2.6 #

0.2.5 #

  • Added apng mime type
  • Added custom mimetype
    So basically if you have a custom mimetype and it does not exists in the given enum, you can add your own mimeType using the field \
String? customMimeType,

and you will have to set the mimetype to custom and call the method like

await FileSaver.instance.saveFile(
                    name: "FileName",
                    link: "www.example.com/file.extention", 
                    filePath: "pathOfFile",
                    file: File(),
                    bytes: bytes,
                    ext: "extention",
                    customMimeType: 'YourCustomType',
                    mimeType: MimeType.custom);
  • Fixed repeated extension when using saveAs with MimeType.other on iOS (GitHub issue #65)

0.2.4 #

  • Bug Fix -> Link Details not available publically

0.2.3 #

  • Replaced the String? link with LinkDetails? link in order to add headers with the link for downloading file
  • Fixed (GitHub issue #59)

0.2.2 #

  • Implemented the web platform without method channel, using the conditional imports.

0.2.1 #

  • Fixed a bug in web (git issue #57)
  • Updated dart version constraints
  • Updated MimeType enum to enhanced enum (from dart 2.17.0) and removed method getMimetype(), if you want to get the mimeType from the enum you can directly write
  MimeType.pdf.type

And if you want the formatted name of the given type, you can get it by

MimeType.pdf.name

0.2.0 #

  • Fixed several issues from github

  • Feature Added a parameter link for saving file directly through network

  • Feature Added filePath if you have the filepath, no need to get the bytes of the file, you can directly pass the path in filePath parameter and the file_saver will do the rest

  • Feature Added file parameter to direct save the file from File object

  • Regardless of all the new options for saving files, bytes parameter is still there and you can still use it but, All the parameters are optional now so you have to use atleast one of these parameter (link, filePath, file, bytes)

  • Changed all the parameters to named instead of positional so now instead of

    await FileSaver.instance.saveFile("FileName", bytes, "extension", mimeType: mimeType);
    
    await FileSaver.instance.saveAs("File", bytes, "extension", type);
    

    you will have to use

    await FileSaver.instance.saveFile(
                      name: "FileName",
                      link: "www.example.com/file.extention", 
                      filePath: "pathOfFile",
                      file: File(),
                      bytes: bytes,
                      ext: "extention",
                      mimeType: type);
    
    await FileSaver.instance.saveFile(
                      name: "FileName",
                      link: "www.example.com/file.extention", 
                      filePath: "pathOfFile",
                      file: File(),
                      bytes: bytes,
                      ext: "extention",
                      mimeType: type);
    
  • Changed the MimeType enum values to lower case (as per dart's naming conventions)

  • Upgraded everything to latest versions (gradle tools = 7.4.2, kotlin=1.8.0)

0.1.1 #

  • Updated the pub to the latest commit, fixing the issues with flutter 3.

0.1.0 #

  • Fixed the incomplete path in saveFile method (GitHub issue #16)
  • Fixed some crashes in some folders on saveAs method with the help of this answer
  • Fixed application crash issue reply already submitted with the help of this suggestion (GitHub issue #14)
  • Fixed Wrong or missing file extension when calling saveAs() (GitHub issue #20)

0.0.12 #

  • Fixed Path Provider version

0.0.11 #

  • Updated Readme
  • Upgraded Path Provider
  • Updated Kotlin version to 1.16.10

0.0.10 #

  • Updated Readme
  • Due to security reasons, I'm not able to save the files to downloads folder in android, if anyone has any idea that would work on Android 11 so please connect.

0.0.9 #

  • Android Permission Bug Fixed
  • Other bugs fixes

0.0.8 #

  • Minor Bug Fixes
  • Updated Readme

0.0.7 #

  • Added Save as method for Android and iOS, more coming soon
  • Bug fixes & Suggestions (Reported on Github)

0.0.6 #

  • Added More File Types

0.0.5 #

  • Minor Bug Fixes

0.0.4 #

  • saveFile method returns the path where the file is saved.

0.0.3 #

  • Minor Bug Fixes

0.0.2 #

  • Updated Guide

0.0.1 #

  • File Saver for all platforms
502
likes
160
points
280k
downloads

Documentation

API reference

Publisher

verified publisherhassanansari.dev

Weekly Downloads

Save files from bytes, paths, streams, and URLs across Android, iOS, Web, Windows, macOS, and Linux.

Homepage
Repository (GitHub)
View/report issues

License

BSD-3-Clause (license)

Dependencies

collection, flutter, flutter_web_plugins, http, meta, path_provider, web

More

Packages that depend on file_saver

Packages that implement file_saver