Unity webgl 获取图片或视频数据

这一版有部分问题,使用最下面的...

WebFilePicker.jslib (放在Plugins目录)

javascript 复制代码
var WebFilePickerLibrary = {
	/**
	 * 从浏览器中获取文件并发送给 Unity WebGL 应用程序。
	 * @param {number} objectNamePtr - Unity 对象名称的指针。
	 * @param {number} funcNamePtr - Unity 回调函数名称的指针。
	 * @param {number} fileTypePtr - 允许的文件类型字符串的指针。
	 * @param {number} allowMultiple - 是否允许多选(1 表示允许多选,0 表示单选)。
	 * @param {number} maxSizeMB - 文件大小限制(单位:MB)。如果 <=0,则无限制。
	 */
	getFileFromBrowser: function(objectNamePtr, funcNamePtr, fileTypePtr, allowMultiple, maxSizeMB) {
		var objectName = UTF8ToString(objectNamePtr);
		var funcName = UTF8ToString(funcNamePtr);
		var fileType = UTF8ToString(fileTypePtr);
		var maxSizeBytes = maxSizeMB > 0 ? maxSizeMB * 1048576 : 0;

		var input = document.createElement("input");
		input.type = "file";
		input.multiple = !!allowMultiple; // 转换为布尔值
		input.accept = fileType;
		input.style.display = "none";

		/**
		 * 处理通用文件
		 * @param {File[]} files - 用户选择的文件列表。
		 */
		var handleFiles = function(files) {
			var results = [];
			var filesProcessed = 0;

			for (let i = 0; i < files.length; i++) {
				const file = files[i];

				// 检查文件大小限制
				if (maxSizeBytes > 0 && file.size > maxSizeBytes) {
					SendMessage(objectName, funcName,
						`error:File '${file.name}' exceeds limit (${(file.size / 1048576).toFixed(1)}MB/${maxSizeMB}MB)`);
					return;
				}

				const reader = new FileReader();
				reader.onload = (e => {
					results.push({
						name: file.name,
						type: file.type,
						data: new Uint8Array(e.target.result)
					});

					filesProcessed++;

					// 所有文件处理完毕时发送结果
					if (filesProcessed === files.length) {
						var resultData = results.map(result => {
							return {
								name: result.name,
								type: result.type,
								data: Array.from(result.data)
							};
						});
						SendMessage(objectName, funcName, JSON.stringify(resultData));
					}
				});

				reader.readAsArrayBuffer(file);
			}
		};

		// 监听文件选择事件
		input.addEventListener('change', function(evt) {
			const files = evt.target.files;
			if (!files || files.length === 0) {
				SendMessage(objectName, funcName, "error:No file selected");
				return;
			}
			handleFiles(files);
		});

		// 触发文件选择对话框
		document.body.appendChild(input);
		input.click();
		document.body.removeChild(input);
	}
};

mergeInto(LibraryManager.library, WebFilePickerLibrary);

WebFilePicker.cs

csharp 复制代码
using System;

namespace MYTOOL
{
    [Serializable]
    public class FileResult
    {
        public string name;     // 文件名称
        public string type;    // MIME 类型
        public byte[] data;    // 二进制数据
    }


    /// <summary>
    /// 提供与Unity WebGL平台交互的方法,用于从浏览器中获取文件(图片、视频或其他类型)
    /// </summary>
    public static class WebFilePicker
    {
        public const string IMAGE_FILE_TYPE = "image/*";
        public const string VIDEO_FILE_TYPE = "video/*";


#if UNITY_WEBGL
        [System.Runtime.InteropServices.DllImport("__Internal")]
        private static extern void getFileFromBrowser(string objName, string methodName, string fileType, bool allowMultiple, int maxSizeMB);
#endif


        /// <summary>
        /// 从浏览器中获取图片文件
        /// </summary>
        /// <param name="objName">Unity对象名称</param>
        /// <param name="methodName">Unity回调方法名称</param>
        /// <param name="maxSizeMB">文件大小限制。如果为0则无限制</param>
        public static void GetImageFromBrowser(string objName, string methodName, int maxSizeMB = 0)
        {
            GetFileFromBrowser(objName, methodName, IMAGE_FILE_TYPE, maxSizeMB);
        }

        /// <summary>
        /// 从浏览器中获取多个图片文件
        /// </summary>
        /// <param name="objName">Unity对象名称</param>
        /// <param name="methodName">Unity回调方法名称</param>
        /// <param name="maxSizeMB">文件大小限制。如果为0则无限制</param>
        public static void GetImagesFromBrowser(string objName, string methodName, int maxSizeMB = 0)
        {
            GetFilesFromBrowser(objName, methodName, IMAGE_FILE_TYPE, maxSizeMB);
        }

        /// <summary>
        /// 从浏览器中获取视频文件
        /// </summary>
        /// <param name="objName">Unity对象名称</param>
        /// <param name="methodName">Unity回调方法名称</param>
        /// <param name="maxSizeMB">文件大小限制。如果为0则无限制</param>
        public static void GetVideoFromBrowser(string objName, string methodName, int maxSizeMB = 0)
        {
            GetFileFromBrowser(objName, methodName, VIDEO_FILE_TYPE, maxSizeMB);
        }

        /// <summary>
        /// 从浏览器中获取任意类型的文件
        /// </summary>
        /// <param name="objName">Unity对象名称</param>
        /// <param name="methodName">Unity回调方法名称</param>
        /// <param name="fileType">文件类型</param>
        /// <param name="maxSizeMB">文件大小限制。如果为0则无限制</param>
        public static void GetFileFromBrowser(string objName, string methodName, string fileType, int maxSizeMB = 0)
        {
#if UNITY_WEBGL && !UNITY_EDITOR
            getFileFromBrowser(objName, methodName, fileType, false, maxSizeMB);
#else
            UnityEngine.Debug.LogError("only implemented for WebGL platform.");
#endif
        }

        /// <summary>
        /// 从浏览器中获取多个任意类型的文件
        /// </summary>
        /// <param name="objName">Unity对象名称</param>
        /// <param name="methodName">Unity回调方法名称</param>
        /// <param name="fileType">文件类型</param>
        /// <param name="maxSizeMB">文件大小限制。如果为0则无限制</param>
        public static void GetFilesFromBrowser(string objName, string methodName, string fileType, int maxSizeMB = 0)
        {
#if UNITY_WEBGL && !UNITY_EDITOR
            getFileFromBrowser(objName, methodName, fileType, true, maxSizeMB);
#else
            UnityEngine.Debug.LogError("only implemented for WebGL platform.");
#endif
        }
    }
}

使用:调用WebFilePicker里提供的方法,回调时返回json字符串,反序列化为FileResult即可拿到原始数据。

注意:mime_type => type

效果:

统一格式返回(数组)

WebFilePicker.jslib (放在Plugins目录)

javascript 复制代码
var WebFilePickerLibrary = {
    /**
     * 从浏览器中获取文件并发送给 Unity WebGL 应用程序。
     * @param {number} objectNamePtr - Unity 对象名称的指针。
     * @param {number} funcNamePtr - Unity 回调函数名称的指针。
     * @param {number} fileTypePtr - 允许的文件类型字符串的指针。
     * @param {number} allowMultiple - 是否允许多选(1 表示允许多选,0 表示单选)。
     * @param {number} maxSizeMB - 文件大小限制。如果<=0则无限制。
     */
    getFileFromBrowser: function (objectNamePtr, funcNamePtr, fileTypePtr, allowMultiple, maxSizeMB) {
        var objectName = UTF8ToString(objectNamePtr);
        var funcName = UTF8ToString(funcNamePtr);
        var fileType = UTF8ToString(fileTypePtr);
        var maxSizeBytes = maxSizeMB > 0 ? maxSizeMB * 1048576 : 0;

        var inputFile = document.createElement("input");
        inputFile.type = "file";
        inputFile.multiple = !!allowMultiple; // 转换为布尔值
        inputFile.accept = fileType;
        inputFile.style.display = "none";

        // 标记是否已完成操作
        let isHandled = false;

        /**
         * 处理通用文件
         * @param {File[]} files - 用户选择的文件列表。
         */
        var handleFiles = function (files) {
            var results = [];
            var filesProcessed = 0;

            for (let i = 0; i < files.length; i++) {
                const file = files[i];

                // 检查文件大小限制
                if (maxSizeBytes > 0 && file.size > maxSizeBytes) {
                    var errorResult = [{
                            result: -3,
                            name: file.name,
                            type: file.type,
                            data: []
                        }
                    ];
                    SendMessage(objectName, funcName, JSON.stringify(errorResult));
                    return;
                }

                const reader = new FileReader();
                reader.onload = (e => {
                    results.push({
                        result: 0,
                        name: file.name,
                        type: file.type,
                        data: Array.from(new Uint8Array(e.target.result))
                    });

                    filesProcessed++;

                    // 所有文件处理完毕时发送结果
                    if (filesProcessed === files.length) {
                        SendMessage(objectName, funcName, JSON.stringify(results));
                    }
                });

                reader.onerror = () => {
                    var errorResult = [{
                            result: -2,
                            name: file.name,
                            type: file.type,
                            data: []
                        }
                    ];
                    SendMessage(objectName, funcName, JSON.stringify(errorResult));
                };

                reader.readAsArrayBuffer(file);
            }
        };

        // 监听文件选择事件
        inputFile.addEventListener('change', function (evt) {
            isHandled = true;
            const files = evt.target.files;

            if (files.length > 0) {
                handleFiles(files);
            } else {
                var cancelResult = [{
                        result: -1,
                        name: "",
                        type: "",
                        data: []
                    }
                ];
                SendMessage(objectName, funcName, JSON.stringify(cancelResult));
            }

            // 清理 focus 监听器
            window.removeEventListener('focus', onFocus);
        });

        // 定义 focus 事件的回调函数
        var onFocus = () => {
            setTimeout(() => {
                if (!isHandled) {
                    var cancelResult = [{
                            result: -1,
                            name: "",
                            type: "",
                            data: []
                        }
                    ];
                    SendMessage(objectName, funcName, JSON.stringify(cancelResult));
                }
            }, 200);
        };

        // 监听窗口焦点事件(部分浏览器取消选择后会触发)
        window.addEventListener('focus', onFocus, {
            once: true
        });

        // 触发文件选择对话框
        document.body.appendChild(inputFile);
        inputFile.click();
        document.body.removeChild(inputFile);
    }
};

mergeInto(LibraryManager.library, WebFilePickerLibrary);
csharp 复制代码
using System;

namespace MYTOOL
{
    [Serializable]
    public class FileSelectionResult
    {
        /// <summary>
        /// <para> 0 正常</para>
        /// <para>-1 取消</para>
        /// <para>-2 加载错误</para>
        /// <para>-3 文件大小超出限制</para>
        /// </summary>
        public int result;

        /// <summary>
        /// 文件名称
        /// </summary>
        public string name;

        /// <summary>
        /// MIME 类型
        /// </summary>
        public string type;

        /// <summary>
        /// 二进制数据
        /// </summary>
        public byte[] data;

        /// <summary>
        /// 是否操作成功
        /// </summary>
        public bool IsSuccess => result == 0;

        /// <summary>
        /// 用户是否取消了操作
        /// </summary>
        public bool IsCancelled => result == -1;

        /// <summary>
        /// 是否发生加载错误
        /// </summary>
        public bool IsLoadError => result == -2;

        /// <summary>
        /// 文件大小是否超出限制
        /// </summary>
        public bool IsSizeExceeded => result == -3;

        /// <summary>
        /// 获取状态描述信息
        /// </summary>
        public string StatusMessage =>
            result switch
            {
                0 => "操作成功",
                -1 => "用户取消",
                -2 => "加载错误",
                -3 => "文件大小超出限制",
                _ => "未知状态"
            };

        /// <summary>
        /// 判断是否有文件数据
        /// </summary>
        public bool HasFileData => data != null && data.Length > 0;

        /// <summary>
        /// 获取文件大小(以字节为单位),如果 data 为空则返回 0
        /// </summary>
        public long GetFileSize() => data?.Length ?? 0;
    }


    /// <summary>
    /// 提供与Unity WebGL平台交互的方法,用于从浏览器中获取文件(图片、视频或其他类型)
    /// </summary>
    public static class WebFilePicker
    {
        public const string IMAGE_FILE_TYPE = "image/*";
        public const string VIDEO_FILE_TYPE = "video/*";


#if UNITY_WEBGL
        [System.Runtime.InteropServices.DllImport("__Internal")]
        private static extern void getFileFromBrowser(string objName, string methodName, string fileType, bool allowMultiple, int maxSizeMB);
#endif


        /// <summary>
        /// 从浏览器中获取图片文件
        /// </summary>
        /// <param name="objName">Unity对象名称</param>
        /// <param name="methodName">Unity回调方法名称</param>
        /// <param name="maxSizeMB">文件大小限制。如果为0则无限制</param>
        public static void GetImageFromBrowser(string objName, string methodName, int maxSizeMB = 0)
        {
            GetFileFromBrowser(objName, methodName, IMAGE_FILE_TYPE, maxSizeMB);
        }

        /// <summary>
        /// 从浏览器中获取多个图片文件
        /// </summary>
        /// <param name="objName">Unity对象名称</param>
        /// <param name="methodName">Unity回调方法名称</param>
        /// <param name="maxSizeMB">文件大小限制。如果为0则无限制</param>
        public static void GetImagesFromBrowser(string objName, string methodName, int maxSizeMB = 0)
        {
            GetFilesFromBrowser(objName, methodName, IMAGE_FILE_TYPE, maxSizeMB);
        }

        /// <summary>
        /// 从浏览器中获取视频文件
        /// </summary>
        /// <param name="objName">Unity对象名称</param>
        /// <param name="methodName">Unity回调方法名称</param>
        /// <param name="maxSizeMB">文件大小限制。如果为0则无限制</param>
        public static void GetVideoFromBrowser(string objName, string methodName, int maxSizeMB = 0)
        {
            GetFileFromBrowser(objName, methodName, VIDEO_FILE_TYPE, maxSizeMB);
        }

        /// <summary>
        /// 从浏览器中获取任意类型的文件
        /// </summary>
        /// <param name="objName">Unity对象名称</param>
        /// <param name="methodName">Unity回调方法名称</param>
        /// <param name="fileType">文件类型</param>
        /// <param name="maxSizeMB">文件大小限制。如果为0则无限制</param>
        public static void GetFileFromBrowser(string objName, string methodName, string fileType, int maxSizeMB = 0)
        {
#if UNITY_WEBGL && !UNITY_EDITOR
            getFileFromBrowser(objName, methodName, fileType, false, maxSizeMB);
#else
            UnityEngine.Debug.LogError("only implemented for WebGL platform.");
#endif
        }

        /// <summary>
        /// 从浏览器中获取多个任意类型的文件
        /// </summary>
        /// <param name="objName">Unity对象名称</param>
        /// <param name="methodName">Unity回调方法名称</param>
        /// <param name="fileType">文件类型</param>
        /// <param name="maxSizeMB">文件大小限制。如果为0则无限制</param>
        public static void GetFilesFromBrowser(string objName, string methodName, string fileType, int maxSizeMB = 0)
        {
#if UNITY_WEBGL && !UNITY_EDITOR
            getFileFromBrowser(objName, methodName, fileType, true, maxSizeMB);
#else
            UnityEngine.Debug.LogError("only implemented for WebGL platform.");
#endif
        }
    }
}
相关推荐
咸鱼永不翻身10 小时前
Unity视频资源压缩详解
unity·游戏引擎·音视频
在路上看风景11 小时前
4.2 OverDraw
unity
在路上看风景11 小时前
1.10 CDN缓存
unity
ellis197021 小时前
Unity插件SafeArea Helper适配异形屏详解
unity
nnsix1 天前
Unity Physics.Raycast的 QueryTriggerInteraction枚举作用
unity·游戏引擎
地狱为王1 天前
Cesium for Unity叠加行政区划线
unity·gis·cesium
esmap1 天前
技术深度解析:ESMap引擎VS主流数字孪生竞品
人工智能·物联网·3d·编辑器·智慧城市·webgl
小贺儿开发1 天前
Unity3D 八大菜系连连看
游戏·unity·互动·传统文化
在路上看风景1 天前
25. 屏幕像素和纹理像素不匹配
unity
ۓ明哲ڪ1 天前
Unity功能——创建新脚本时自动添加自定义头注释
unity·游戏引擎