Skip to content

About

A native file browser for unity standalone platforms

Topics

Resources

Stars

33 stars

Watchers

0 watching

Forks

 
 

Latest commit

 

History

83 Commits

Folders and files

Repository files navigation

Unity Standalone File Browser

openupm

A simple wrapper for native file dialogs on Windows/Mac/Linux, plus a dedicated WebGL browser file API.

Installation

Add from OpenUPM | via scoped registry, recommended

To add OpenUPM to your project:

  • open Edit/Project Settings/Package Manager
  • add a new Scoped Registry:
Name: OpenUPM
URL:  https://package.openupm.com/
Scope(s): io.github.gkngkc.unity-standalone-file-browser
  • click Save
  • open Package Manager
  • Select My Registries in dropdown top left
  • Select Unity Standalone File Browser and click Install
Add from GitHub | not recommended, no updates through PackMan

You can also add it directly from GitHub on Unity 2019.4+. Note that you won't be able to receive updates through Package Manager this way, you'll have to update manually.

  • open Package Manager
  • click +
  • select Add from Git URL
  • paste https://github.com/shiena/UnityStandaloneFileBrowser.git?path=Packages/StandaloneFileBrowser#upm
  • click Add

Example usage:

// Open file
var paths = StandaloneFileBrowser.OpenFilePanel("Open File", "", "", false);

// Open file async
StandaloneFileBrowser.OpenFilePanelAsync("Open File", "", "", false, (string[] paths) => {  });

// Open file with filter
var extensions = new [] {
    new ExtensionFilter("Image Files", "png", "jpg", "jpeg" ),
    new ExtensionFilter("Sound Files", "mp3", "wav" ),
    new ExtensionFilter("All Files", "*" ),
};
var paths = StandaloneFileBrowser.OpenFilePanel("Open File", "", extensions, true);

// Save file
var path = StandaloneFileBrowser.SaveFilePanel("Save File", "", "", "");

// Save file async
StandaloneFileBrowser.SaveFilePanelAsync("Save File", "", "", "", (string path) => {  });

// Save file with filter
var extensionList = new [] {
    new ExtensionFilter("Binary", "bin"),
    new ExtensionFilter("Text", "txt"),
};
var path = StandaloneFileBrowser.SaveFilePanel("Save File", "", "MySaveFile", extensionList);

See Sample/BasicSampleScene.unity for more detailed examples.

Mac Screenshot Alt text

Windows Screenshot Alt text

Linux Screenshot Alt text

Notes:

  • Windows

    • Requires .NET 3.5 or higher api compatibility level
    • Async dialog opening not implemented, ..Async methods simply calls regular sync methods.
    • Plugin import settings should be like this;

    Alt text Alt text

  • Mac

    • Sync calls are throws an exception at development build after native panel loses and gains focus. Use async calls to avoid this.

WebGL:

  • WebGL uses the dedicated StandaloneFileBrowserWebGL API instead of the desktop StandaloneFileBrowser path-based API.
  • The desktop StandaloneFileBrowser API is intentionally unavailable in WebGL builds; use explicit platform branching.
  • Opening files returns temporary browser file references (WebGLFileReference) with ObjectUrl, Name, Size, MimeType, and LastModifiedUnixMs metadata.
  • Recommended read path is ObjectUrl + UnityWebRequest / UnityWebRequestTexture, then explicit Release(...) after the read completes.
  • Saving uses SaveFileAsync(fileName, data[, mimeType]) and triggers a browser download rather than a native save dialog.
  • File filters are picker hints only.
  • Browser limitations still apply: meaningful title / default-directory semantics are not available. For opening and saving files, call the API from IPointerDownHandler.OnPointerDown, as in the canvas samples; the JS bridge arms the request and triggers the picker or download on the next native pointerup event. Do not use Button.onClick, keyboard activation, or delayed/programmatic calls with this implementation.
  • When the browser exposes navigator.userActivation, both open and save check transient activation in the native pointerup handler immediately before invoking the picker or download, allowing touch activation to become available on release. A failed check returns BlockedByBrowser for either operation. Browser policy can also block a picker or download without reporting an error to the plugin.
  • Save copies the supplied bytes and prepares the Blob synchronously; only activation checking and download triggering wait for pointerup. Success means the download was triggered, not that the file was written to disk.
  • An armed open or save request completes with Cancelled and releases its resources when a native pointercancel occurs, or when a new pointerdown occurs before the expected release. The new press is handled after the cancellation, so it can start a fresh request.
  • Unity processes OnPointerDown in its frame loop, after the native event. If the pointer is released before Unity handles the press (for example, a very quick tap at a low frame rate), the request misses its pointerup and nothing opens. The next press cancels that request with Cancelled and can start a new one.
  • First-version concurrency is one open request and one save request at a time.

Result status

Both WebGLFileSelectionResult.Status and WebGLSaveResult.Status use the shared WebGLFileBrowserStatus enum:

Status Open Save
Success Files were selected. The download was triggered; completion is not observed.
Cancelled The picker was cancelled, or the request was abandoned before the picker opened. The Editor save dialog was cancelled, or the request was abandoned before the download was triggered.
BlockedByBrowser The activation check failed before opening the picker. The activation check failed before triggering the download.
Busy Another open request is pending. Another save request is pending.
Error A file operation, bridge call, or response failed. Data preparation, download triggering, or a bridge call/response failed.

A browser download's cancellation after triggering cannot be observed by this API. BlockedByBrowser identifies a detected activation failure, not every possible browser restriction; some restrictions can silently prevent an operation.

Browser compatibility

File-picker cancellation relies on the HTMLInputElement cancel event. The supported minimum versions for this cancellation behavior are Chrome / Edge 113, Firefox 91, and Safari / iOS Safari 16.4 (Chrome for Android: 113). These are the minimum versions for this event, not a guarantee of compatibility with every Unity WebGL build; the Unity version and other browser requirements also apply.

Older browsers are not supported for reliable file-picker cancellation. Without the cancel event, closing the picker without selecting a file may leave the request pending, and subsequent open requests can return Busy. ReleaseAll() releases file references and object URLs only; it does not cancel or reset pending requests. There is currently no cancellation fallback or public request-reset API. The new-pointerdown guard only cancels a request whose pointer release was missed before the picker opens; it is not a fallback for cancelling an already-open picker.

Example WebGL usage:

using System.Collections;
using SFB;
using UnityEngine;
using UnityEngine.Networking;

public void OpenTextFile() {
    StandaloneFileBrowserWebGL.OpenFilePanelAsync("txt", false, result => {
        if (result.Status == WebGLFileBrowserStatus.Cancelled) {
            return;
        }

        if (result.Status == WebGLFileBrowserStatus.BlockedByBrowser) {
            Debug.LogWarning(result.ErrorMessage);
            return;
        }

        if (result.Status != WebGLFileBrowserStatus.Success || result.Files.Length == 0) {
            return;
        }

        var file = result.Files[0];
        StartCoroutine(ReadTextAndRelease(file));
    });
}

private IEnumerator ReadTextAndRelease(WebGLFileReference file) {
    var request = UnityWebRequest.Get(file.ObjectUrl);
    yield return request.SendWebRequest();

    if (request.result == UnityWebRequest.Result.Success) {
        Debug.Log(request.downloadHandler.text);
    }

    StandaloneFileBrowserWebGL.Release(file);
}

public void SaveTextFile(byte[] bytes) {
    StandaloneFileBrowserWebGL.SaveFileAsync("sample.txt", bytes, result => {
        Debug.Log(result.Status);
    });
}

Live Demo: https://gkngkc.github.io/

About

A native file browser for unity standalone platforms

Topics

Resources

Stars

33 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages