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
        }
    }
}
相关推荐
benben0441 小时前
Unity3D仿星露谷物语开发36之锄地动画2
游戏·ui·unity·游戏引擎
DanmF--14 小时前
详解与HTTP服务器相关操作
服务器·网络·网络协议·http·unity·c#
江沉晚呤时16 小时前
从零开始学习 Lucene.Net:.NET Core 中的全文搜索与索引管理
开发语言·c#·.net·mybatis·.netcore·lucene
重生之我在火星学前端17 小时前
WebGL学习之路:1. 理论基础
前端·webgl·three.js
年少无知且疯狂3 天前
C# 对列表中的元素的多个属性进行排序
unity·c#·游戏引擎
Mapmost3 天前
【数据融合实战手册·实战篇】二维赋能三维的5种高阶玩法:手把手教你用Mapmost打造智慧城市标杆案例
webgl
zaizai10073 天前
Unity 一些小功能(屏幕画画,)
unity
归海_一刀3 天前
【Unity动态换装骨骼合并】
unity·c#·游戏引擎
爱shader的锐雯3 天前
Unity基于屏幕空间的鼠标拖动,拖动物体旋转
unity·计算机外设·游戏引擎