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
        }
    }
}
相关推荐
天人合一peng3 小时前
unity 生成标记根据背景色标记变色
unity·游戏引擎
天人合一peng7 小时前
unity 生成标记根据背景色变色为明显的颜色
unity·游戏引擎
魔士于安8 小时前
Unity 超市总动员 超市收银台 超市货架 超市购物手推车 超市常见商品
游戏·unity·游戏引擎·贴图·模型
CandyU28 小时前
Unity —— 数据持久化
unity·游戏引擎
zh路西法8 小时前
【Unity实现Oneshot胶卷显形】游戏窗口化与Win32API的使用
游戏·unity·游戏引擎
risc12345612 小时前
writeBlocks
lucene
凡情13 小时前
android隐私合规检测
android·unity
小贺儿开发13 小时前
Unity3D 本地 Stable Diffusion 文生图效果演示
人工智能·unity·stable diffusion·文生图·ai绘画·本地化
mxwin1 天前
Unity Shader 半透明物体为什么不能写入深度缓冲?
unity·游戏引擎·shader
晚枫歌F1 天前
三层时间轮的实现
网络·unity·游戏引擎