File Uploading from local storage to Unity Webgl application

When it comes to webGL output, my code works flawlessly for the Unity editor and standalone output versions, but not when it comes to uploading an external file from local storage to the Unity webGL application during runtime. I’ve tried adding jslib plugins, but the file upload dialogue box appears for file selection, but the selected file is not passed inside the webGL canvas to display. Any assistance would be greatly welcomed as I am new to Unity WebGL and have no prior expertise with web-related applications.










Error in webgl


Webgl Plugin Script:

 mergeInto(LibraryManager.library, {
    OpenFileInputJS: function () {
        var fileInput = document.getElementById('fileInput');
        fileInput.addEventListener('change', function (event) {
            var filePath = event.target.value; // Get the file path directly from the input's value
            // Check if the Module object exists
            if (typeof Module !== "undefined" && Module.RuntimeMonoBehaviour_invoke_method) {
               
            // Ensure that the file path is not empty
         if (filePath) {
             Module.RuntimeMonoBehaviour_invoke_method(
            Module.RuntimeMonoBehaviour_methods.OnFileSelected,
            [filePath]
        );
    }
} else 
    {
            console.error("Module or RuntimeMonoBehaviour_invoke_method is undefined. Check your Unity WebGL setup.");
    }
        }, false);
        fileInput.click();
    }
});


Webgl File Uploading Script:

#if UNITY_WEBGL

using UnityEngine;
using UnityEngine.UI;
using itk.simple;
using System.Runtime.InteropServices;

namespace UnityVolumeRendering
{
    public class FileUpload : MonoBehaviour
    {
        // Reference to the HTML file input element
        private string fileInputId = "fileInput";
        private string openButtonId = "openButton";

       //public VolumeRenderedObject obj;


        private void Start()
        {
            // Hook up the Open button click event to open the file input dialog
            var openButton = GameObject.Find(openButtonId).GetComponent<Button>();
            openButton.onClick.AddListener(OpenFileInput);
        }

        // Function to open the file input dialog
        private void OpenFileInput()
        {
            // Verify that the application is running in WebGL
            if (Application.platform == RuntimePlatform.WebGLPlayer)
            {
                // Use JavaScript Interop to trigger the file input element
                OpenFileInputJS();
            }
            else
            {
                Debug.LogError("File input is only supported in WebGL builds.");
            }
        }

        // JavaScript Interop function to trigger file input
        [DllImport("__Internal")]
        private static extern void OpenFileInputJS();

        // Callback function called from JavaScript after a file is selected
        public void OnFileSelected(string filePath)
        {
            if (!string.IsNullOrEmpty(filePath))
            {
                Debug.Log("filePath: " + filePath);
                if (Application.platform == RuntimePlatform.WebGLPlayer)
                {
                    // Handle the selected file (e.g., import and render it)
                    HandleSelectedFile(filePath);
                }
            }


        }


        // Function to handle the selected file
        private void HandleSelectedFile(string filePath)
        {
            // Handle the file as needed (e.g., import and render it)
            if (!string.IsNullOrEmpty(filePath))
            {
                // Determine the file type and import/render accordingly
                if (filePath.ToLower().EndsWith(".nii"))
                {
                    IImageFileImporter importer = ImporterFactory.CreateImageFileImporter(ImageFileFormat.NIFTI);
                    VolumeDataset dataset = importer.Import(filePath);

                    if (dataset != null)
                    {
                        // Ensure the volume rendering object (obj) is correctly set up in the Unity scene
                        // Assign the created VolumeRenderedObject to the public obj field
                        VolumeRenderedObject obj = VolumeObjectFactory.CreateObject(dataset);

                        // Additional configuration for materials, shaders, and camera may be required here
                    }
                    else
                    {
                        Debug.LogError("Failed to import dataset.");
                    }
                }
                else
                {
                    Debug.LogWarning("Unsupported file format.");
                }
            }
            else
            {
                Debug.LogWarning("Invalid file path.");
            }
        }
    }
}
#endif

Runtime file Uploading script that works perfectly for editor and Standalone output:


#if UVR_USE_SIMPLEITK
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEngine;
using System.Runtime.InteropServices;
using UnityEngine.Networking;
using System.Text;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using UnityEditor;
using itk.simple;

namespace UnityVolumeRendering
{
    /// <summary>
    /// This is a basic runtime GUI, that can be used during play mode.
    /// You can import datasets, and edit them.
    /// Add this component to an empty GameObject in your scene (it's already in the test scene) and click play to see the GUI.
    /// </summary>
    public class RuntimeGUI : MonoBehaviour 
    {


        private string filePath;

        //public Button uploadButton;


        

       /* void Start()
        {
            uploadButton.onClick.AddListener(OnOpenDICOMDatasetResult(result));
        }
*/
        
        private void OnGUI()
        {
            GUILayout.BeginVertical();


           

            /*if (GUILayout.Button("Import DICOM dataset"))
            {
                RuntimeFileBrowser.ShowOpenDirectoryDialog(OnOpenDICOMDatasetResult);

            }*/

            if (GUILayout.Button("Import NIFTI dataset"))
            {
                RuntimeFileBrowser.ShowOpenFileDialog(OnOpenNIFTIDatasetResult);

            }


            // Show button for opening the dataset editor (for changing the visualisation)
            if (GameObject.FindObjectOfType<VolumeRenderedObject>() != null && GUILayout.Button("Edit DataSet Volume"))
            {
                EditVolumeGUI.ShowWindow(GameObject.FindObjectOfType<VolumeRenderedObject>());
            }

            // Show button for opening the slicing plane editor (for changing the orientation and position)
            if (GameObject.FindObjectOfType<SlicingPlane>() != null && GUILayout.Button("Edit Slicer"))
            {
                EditSliceGUI.ShowWindow(GameObject.FindObjectOfType<SlicingPlane>());
            }
            if (GameObject.FindObjectOfType<CrossSectionPlane>() != null && GUILayout.Button("Edit Cross Section "))
            {
                EditCrossSectionPlaneGUI.ShowWindow(GameObject.FindObjectOfType<CrossSectionPlane>());

            }

            GUILayout.EndVertical();
        }

        

        private void OnOpenNIFTIDatasetResult(RuntimeFileBrowser.DialogResult result)
        {
            if (!result.cancelled)
            {
                DespawnAllDatasets();
                string filePath = result.path;

                StartCoroutine(LoadFile(filePath, (www) =>
                {
                    // Save the byte array to a temporary file
                    string tempFilePath = Path.Combine(Application.persistentDataPath, "temp_dataset.nii");
                    File.WriteAllBytes(tempFilePath, www.downloadHandler.data);

                    // Now use the temp file path for importing
                    IImageFileImporter importer = ImporterFactory.CreateImageFileImporter(ImageFileFormat.NIFTI);
                    VolumeDataset dataset = importer.Import(tempFilePath);

                    if (dataset != null)
                    {
                        VolumeRenderedObject obj = VolumeObjectFactory.CreateObject(dataset);
                    }

                    // Cleanup: Delete the temporary file
                    File.Delete(tempFilePath);
                }));
            }
        }


        




        public void OnOpenDICOMDatasetResult(RuntimeFileBrowser.DialogResult result)
        {
            if (!result.cancelled)
            {
                // We'll only allow one dataset at a time in the runtime GUI (for simplicity)
                DespawnAllDatasets();

                bool recursive = true;

                // Read all files
                IEnumerable<string> fileCandidates = Directory.GetFiles(result.path, "*.*", recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly)
                    .Where(p => p.EndsWith(".dcm", StringComparison.InvariantCultureIgnoreCase) || p.EndsWith(".dicom", StringComparison.InvariantCultureIgnoreCase) || p.EndsWith(".dicm", StringComparison.InvariantCultureIgnoreCase) || p.EndsWith(".IMA", StringComparison.InvariantCultureIgnoreCase) || p.EndsWith(".nii", StringComparison.InvariantCultureIgnoreCase));

                // Import the dataset
                IImageSequenceImporter importer = ImporterFactory.CreateImageSequenceImporter(ImageSequenceFormat.DICOM);
                IEnumerable<IImageSequenceSeries> seriesList = importer.LoadSeries(fileCandidates);
                float numVolumesCreated = 0;
                foreach (IImageSequenceSeries series in seriesList)
                {
                    VolumeDataset dataset = importer.ImportSeries(series);
                    // Spawn the object
                    if (dataset != null)
                    {
                        VolumeRenderedObject obj = VolumeObjectFactory.CreateObject(dataset);
                        obj.transform.position = new Vector3(numVolumesCreated, 0, 0);
                        numVolumesCreated++;
                    }
                }
                

            }
            
        }
        



           

        private IEnumerator LoadFile(string filePath, Action<UnityWebRequest> callback)
        {
            UnityWebRequest www = UnityWebRequest.Get(filePath);
            yield return www.SendWebRequest();

            if (www.result == UnityWebRequest.Result.ConnectionError || www.result == UnityWebRequest.Result.ProtocolError)
            {
                Debug.LogError(www.error);
            }
            else
            {
                callback(www);
            }
        }

        private void DespawnAllDatasets()
        {
            VolumeRenderedObject[] volobjs = GameObject.FindObjectsOfType<VolumeRenderedObject>();
            foreach (VolumeRenderedObject volobj in volobjs)
            {
                GameObject.Destroy(volobj.gameObject);
            }
        }




    }


}
#endif

RuntimeFileBrowserComponent script:

using System;
using System.IO;
using UnityEngine;
using System.Runtime.InteropServices;
using UnityEngine.Networking;
using System.Text;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
using UnityEngine.EventSystems;


namespace UnityVolumeRendering
{
    public partial class RuntimeFileBrowser
    {
        /// <summary>
        /// Internal MonoBehaviour that shows the GUI of the file browser.
        /// </summary>
        [RequireComponent(typeof(Button))]
        public class RuntimeFileBrowserComponent : MonoBehaviour
        {
            public enum DialogMode
            {
                OpenFile,
                OpenDirectory,
                SaveFile
            }

            public DialogMode dialogMode = DialogMode.OpenFile;
            public DialogCallback callback = null;

            public string currentDirectory = "";
            private string selectedFile = "";
            private string fileName = "";
            private Vector2 scrollPos = Vector2.zero;
            private Vector2 dirScrollPos = Vector2.zero;

            private Rect windowRect = new Rect(100, 50, WINDOW_WIDTH, WINDOW_HEIGHT);

            private const int LEFT_PANEL_WIDTH = 150;
            private const int RIGHT_PANEL_WIDTH = 450;
            private const int WINDOW_WIDTH = 600;
            private const int WINDOW_HEIGHT = 300;

            private int windowID;

            private void Awake()
            {
                // Fetch a unique ID for our window (see GUI.Window)
                windowID = WindowGUID.GetUniqueWindowID();
            }

            private void OnGUI()
            {
                windowRect = GUI.Window(windowID, windowRect, UpdateWindow, "File browser");
            }

            private void UpdateWindow(int windowID)
            {
                GUI.DragWindow(new Rect(0, 0, 10000, 20));

                TextAnchor oldAlignment = GUI.skin.label.alignment;
                GUI.skin.button.alignment = TextAnchor.MiddleLeft;

                GUILayout.BeginVertical();

                DrawTopPanel();

                GUILayout.BeginHorizontal();

                DrawLeftSideMenu();

                DrawDirectoryView();

                GUILayout.FlexibleSpace();

                GUILayout.EndHorizontal();

                DrawBottomBar();

                GUILayout.EndVertical();

                GUI.skin.button.alignment = oldAlignment;
            }

            private void DrawTopPanel()
            {
                GUILayout.BeginHorizontal();

                // "Back" button
                if (GUILayout.Button("Back", GUILayout.Width(LEFT_PANEL_WIDTH)))
                {
                    DirectoryInfo parentDir = Directory.GetParent(currentDirectory);
                    if (parentDir != null)
                        currentDirectory = parentDir.FullName;
                    else
                        currentDirectory = "";
                    scrollPos = Vector2.zero;
                }
                // Show current directory path
                currentDirectory = GUILayout.TextField(currentDirectory, GUILayout.Width(RIGHT_PANEL_WIDTH));

                GUILayout.EndHorizontal();
            }
            
            private void DrawLeftSideMenu()
            {
                GUILayout.BeginVertical(GUILayout.Width(LEFT_PANEL_WIDTH));

                dirScrollPos = GUILayout.BeginScrollView(dirScrollPos);

                if (GUILayout.Button("Documents"))
                {
                    currentDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
                    scrollPos = Vector2.zero;
                }
                if (GUILayout.Button("Desktop"))
                {
                    currentDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
                    scrollPos = Vector2.zero;
                }

                foreach (DriveInfo driveInfo in DriveInfo.GetDrives())
                {
                    if (GUILayout.Button(driveInfo.Name))
                    {
                        currentDirectory = driveInfo.Name;
                        scrollPos = Vector2.zero;
                    }
                }

                GUILayout.EndScrollView();

                GUILayout.EndVertical();
            }

            private void DrawDirectoryView()
            {
                GUILayout.BeginVertical();

                // Draw directory content
                if (!string.IsNullOrEmpty(currentDirectory) && Directory.Exists(currentDirectory))
                {
                    scrollPos = GUILayout.BeginScrollView(scrollPos);
                    // Draw directories
                    foreach (string dir in Directory.GetDirectories(currentDirectory))
                    {
                        DirectoryInfo dirInfo = new DirectoryInfo(dir);
                        if (GUILayout.Button(dirInfo.Name))
                        {
                            currentDirectory = dir;
                        }
                    }
                    // Draw files
                    if (dialogMode == DialogMode.OpenFile || dialogMode == DialogMode.SaveFile)
                    {
                        foreach (string file in Directory.GetFiles(currentDirectory))
                        {
                            FileInfo fileInfo = new FileInfo(file);
                            if (GUILayout.Button(fileInfo.Name))
                            {
                                selectedFile = fileInfo.FullName;
                                fileName = Path.GetFileName(selectedFile);
                            }
                        }
                    }
                    GUILayout.EndScrollView();
                }
                GUILayout.EndVertical();
            }

            private void DrawBottomBar()
            {
                GUILayout.BeginHorizontal();

                if(dialogMode == DialogMode.OpenFile || dialogMode == DialogMode.SaveFile)
                {
                    if (!string.IsNullOrEmpty(selectedFile) || dialogMode == DialogMode.SaveFile)
                    {
                        // Show filename textbox
                        fileName = GUILayout.TextField(fileName, GUILayout.Width(RIGHT_PANEL_WIDTH));
                        if (fileName.Length > 0)
                            selectedFile = Path.Combine(currentDirectory, fileName);
                        GUILayout.FlexibleSpace();
                        // Show button
                        string buttonText = dialogMode == DialogMode.OpenFile ? "Open" : "Save";
                        if (!string.IsNullOrEmpty(fileName) && (File.Exists(selectedFile) || dialogMode == DialogMode.SaveFile) && GUILayout.Button(buttonText))
                        {
                            CloseBrowser(false, selectedFile);
                        }
                    }
                }
                else if(dialogMode == DialogMode.OpenDirectory)
                {
                    if (!string.IsNullOrEmpty(currentDirectory))
                    {
                        // Show directory path textbox
                        currentDirectory = GUILayout.TextField(currentDirectory, GUILayout.Width(RIGHT_PANEL_WIDTH));
                        GUILayout.FlexibleSpace();
                        // Show button
                        string buttonText ="Open";
                        if (Directory.Exists(currentDirectory) && GUILayout.Button(buttonText))
                        {
                            CloseBrowser(false, currentDirectory);
                        }
                    }
                }

                GUILayout.FlexibleSpace();
                if (GUILayout.Button("Cancel"))
                {
                    CloseBrowser(true, "");
                }

                GUILayout.EndHorizontal();
            }

            private void CloseBrowser(bool cancelled, string selectedPath)
            {
                DialogResult result;
                result.cancelled = cancelled;
                result.path = selectedPath;

                callback?.Invoke(result);

                GameObject.Destroy(this.gameObject);
            }
        }
    }
}