Unity实现网页端 打开本地文件选择图片上传到阿里云的OSS

第一步 在Plugins文件下创建 OSSFileUploader.jslib(用记事本创建,更改后缀名就行)文件

csharp 复制代码
mergeInto(LibraryManager.library, {
    // Global variables for callback functions
    uploadCallback: null,
    statusCallback: null,

    // Initialize uploader
    InitializeUploader: function() {
        // Create hidden file input element
        var fileInput = document.createElement('input');
        fileInput.type = 'file';
        fileInput.id = 'unityFileInput';
        fileInput.style.display = 'none';
        document.body.appendChild(fileInput);

        // Listen for file selection events
        fileInput.addEventListener('change', async function(event) {
            var file = event.target.files[0];
            if (file) {
                console.log('Unity selected file:', file.name);
                
                // Get global scope safely within the event handler
                var globalScope;
                if (typeof window !== 'undefined') {
                    globalScope = window;
                } else if (typeof global !== 'undefined') {
                    globalScope = global;
                } else if (typeof self !== 'undefined') {
                    globalScope = self;
                } else {
                    globalScope = {};
                }
                
                // Call Unity callback function
                if (globalScope.uploadCallbackObjectName && globalScope.uploadCallbackMethodName) {
                    SendMessage(globalScope.uploadCallbackObjectName, globalScope.uploadCallbackMethodName, file.name);
                }
                
                // Start upload - inline all functionality here
                try {
                    // Notify Unity of status update
                    if (globalScope.statusCallbackObjectName && globalScope.statusCallbackMethodName) {
                        SendMessage(globalScope.statusCallbackObjectName, globalScope.statusCallbackMethodName, "Getting upload signature...");
                    }

                    // Generate timestamped filename
                    var now = new Date();
                    var timestamp = now.getFullYear() +
                        String(now.getMonth() + 1).padStart(2, '0') +
                        String(now.getDate()).padStart(2, '0') +
                        String(now.getHours()).padStart(2, '0') +
                        String(now.getMinutes()).padStart(2, '0') +
                        String(now.getSeconds()).padStart(2, '0');
					
					const random = Math.random().toString(36).substr(2, 9);
					const timestamp_random = `${timestamp}_${random}`;
                    var nameWithoutExt = file.name.substring(0, file.name.lastIndexOf('.'));
                    var extension = file.name.substring(file.name.lastIndexOf('.'));
                    var filename_Timestamp = nameWithoutExt + '_' + timestamp_random + extension;

                    console.log('Original filename:', file.name);
                    console.log('Timestamped filename:', filename_Timestamp);

                    // Get OSS upload signature  这个地址找你们管理OSS的人员要
                    var response = await fetch("OSS上传获取临时授权地址", {
                        method: "GET"
                    });

                    if (!response.ok) {
                        throw new Error("Failed to get signature");
                    }

                    var res = await response.json();
                    if (res.code !== 200) {
                        throw new Error("Failed to get credentials");
                    }

                    var signatureData = res.data;

                    // Notify Unity of status update
                    if (globalScope.statusCallbackObjectName && globalScope.statusCallbackMethodName) {
                        SendMessage(globalScope.statusCallbackObjectName, globalScope.statusCallbackMethodName, "Uploading file...");
                    }

                    // Prepare upload data
                    var dir_file = signatureData.upload_dir + filename_Timestamp;
                    var formData = new FormData();

                    formData.append("success_action_status", "200");
                    formData.append("policy", signatureData.policy);
                    formData.append("x-oss-signature", signatureData.signature);
                    formData.append("x-oss-signature-version", "OSS4-HMAC-SHA256");
                    formData.append("x-oss-credential", signatureData.x_oss_credential);
                    formData.append("x-oss-date", signatureData.x_oss_date);
                    formData.append("key", dir_file);
                    formData.append("x-oss-security-token", signatureData.security_token);
                    formData.append("file", file);

                    console.log("Upload URL:", signatureData.host + signatureData.upload_dir + filename_Timestamp);

                    // Upload file to OSS
                    var uploadResponse = await fetch(signatureData.host, {
                        method: "POST",
                        body: formData
                    });

                    if (!uploadResponse.ok) {
                        throw new Error("Upload failed");
                    }

                    // Success - notify Unity
                    var fileUrl = signatureData.host + signatureData.upload_dir + filename_Timestamp;
                    
                    // Store upload information for JSON retrieval
                    globalScope.lastUploadInfo = {
                        "selectedFile": file.name,
                        "originalFilename": file.name,
                        "timestampedFilename": filename_Timestamp,
                        "uploadUrl": fileUrl,
                        "fileUrl": fileUrl,
                        "uploadTime": new Date().toISOString(),
                        "status": "success"
                    };
                    
                    if (globalScope.statusCallbackObjectName && globalScope.statusCallbackMethodName) {
                        SendMessage(globalScope.statusCallbackObjectName, globalScope.statusCallbackMethodName, "File uploaded successfully!");
                    }

                    console.log("Upload successful, file URL:", fileUrl);
                    
                    // Call Unity callback function, pass file URL
                    if (globalScope.uploadCallbackObjectName && globalScope.uploadCallbackMethodName) {
                        SendMessage(globalScope.uploadCallbackObjectName, globalScope.uploadCallbackMethodName, fileUrl);
                    }

                } catch (error) {
                    console.error("Error occurred during upload:", error);
                    
                    // Notify Unity of upload failure
                    if (globalScope.statusCallbackObjectName && globalScope.statusCallbackMethodName) {
                        SendMessage(globalScope.statusCallbackObjectName, globalScope.statusCallbackMethodName, "Upload failed: " + error.message);
                    }
                }
              
            }
        });

        console.log('Unity file uploader initialized successfully');
    },

    // Trigger file selection
    SelectFile: function() {
        var fileInput = document.getElementById('unityFileInput');
        if (fileInput) {
            fileInput.click();
        }
    },

    // Set status callback function
    SetStatusCallback: function(objectNamePtr, methodNamePtr) {
        // Get global scope safely
        var globalScope;
        if (typeof window !== 'undefined') {
            globalScope = window;
        } else if (typeof global !== 'undefined') {
            globalScope = global;
        } else if (typeof self !== 'undefined') {
            globalScope = self;
        } else {
            globalScope = {};
        }
        
        var objectName = UTF8ToString(objectNamePtr);
        var methodName = UTF8ToString(methodNamePtr);
        
        globalScope.statusCallbackObjectName = objectName;
        globalScope.statusCallbackMethodName = methodName;
        
        console.log('Status callback set successfully for object:', objectName, 'method:', methodName);
    },

    // Set upload complete callback function
    SetUploadCallback: function(objectNamePtr, methodNamePtr) {
        // Get global scope safely
        var globalScope;
        if (typeof window !== 'undefined') {
            globalScope = window;
        } else if (typeof global !== 'undefined') {
            globalScope = global;
        } else if (typeof self !== 'undefined') {
            globalScope = self;
        } else {
            globalScope = {};
        }
        
        var objectName = UTF8ToString(objectNamePtr);
        var methodName = UTF8ToString(methodNamePtr);
        
        globalScope.uploadCallbackObjectName = objectName;
        globalScope.uploadCallbackMethodName = methodName;
        
        console.log('Upload callback set successfully for object:', objectName, 'method:', methodName);
    },

    // Get upload information as JSON string
    GetUploadInfoAsJson: function() {
        // Get global scope safely
        var globalScope;
        if (typeof window !== 'undefined') {
            globalScope = window;
        } else if (typeof global !== 'undefined') {
            globalScope = global;
        } else if (typeof self !== 'undefined') {
            globalScope = self;
        } else {
            globalScope = {};
        }

        // Check if upload info exists
        if (!globalScope.lastUploadInfo) {
            return null;
        }

        // Convert upload info to JSON string
        var jsonString = JSON.stringify(globalScope.lastUploadInfo);
        
        // Allocate memory for the string and return pointer
        var bufferSize = lengthBytesUTF8(jsonString) + 1;
        var buffer = _malloc(bufferSize);
        stringToUTF8(jsonString, buffer, bufferSize);
        return buffer;
    },

});

第二步 创建C#代码

csharp 复制代码
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using System.Runtime.InteropServices;
using System;

public class FileUploadUI : MonoBehaviour
{
    [Header("UI组件")]
    public Button uploadButton, infoButton;
    public TextMeshProUGUI statusText;
    public TextMeshProUGUI resultText;

    // C# 代码示例
    [DllImport("__Internal")]
    private static extern void InitializeUploader();

    [DllImport("__Internal")]
    private static extern string SelectFile();

    [DllImport("__Internal")]
    private static extern void SetStatusCallback(string objectName, string methodName);

    [DllImport("__Internal")]
    private static extern void SetUploadCallback(string objectName, string methodName);

    [DllImport("__Internal")]
    private static extern string GetUploadInfoAsJson();

    // 使用
    void Start()
    {


        //先点击初始化
        infoButton.onClick.AddListener(GetUploadInfoJson);
        //再点击上传
        uploadButton.onClick.AddListener(OnSelectFileClick);
#if UNITY_WEBGL && !UNITY_EDITOR
 InitializeUploader();
                SetStatusCallback(gameObject.name, "OnStatusUpdate");
                SetUploadCallback(gameObject.name, "OnUploadComplete");
#endif
    }


    void OnSelectFileClick()
    {
        string fileUrl = SelectFile();
        resultText.text = "文件名:" + fileUrl;
        Debug.Log("文件名:" + fileUrl);
    }

    public void OnStatusUpdate(string status)
    {
        Debug.Log("状态更新: " + status);
        statusText.text = status;
    }

    public void OnUploadComplete(string fileUrl)
    {
        Debug.Log("上传完成,文件URL: " + fileUrl);
        //可以通过这个URL地址把 图片加载出来,赋值给Image,
        resultText.text = fileUrl;

        // 获取JSON格式的上传信息
        GetUploadInfoJson();
    }

    public void GetUploadInfoJson()
    {
#if UNITY_WEBGL && !UNITY_EDITOR
            string jsonInfo = GetUploadInfoAsJson();
            if (!string.IsNullOrEmpty(jsonInfo))
            {
                Debug.Log("上传信息JSON: " + jsonInfo);
                resultText.text ="信息:"+ jsonInfo;
            }
            else
            {
                Debug.Log("没有找到上传信息");
            }
#else
        Debug.Log("该功能仅在WebGL平台可用");
#endif
    }
}
相关推荐
爱吃小胖橘4 小时前
Unity-角色控制器
3d·unity·c#·游戏引擎
新石器程序员6 小时前
借鉴bevy实现适用于Godot-rust的状态管理
rust·游戏引擎·godot·bevy
Kaaras9 小时前
游戏引擎以及游戏开发
游戏引擎
绀目澄清10 小时前
unity3d PuppetMaster 布娃娃插件在学习
unity
PaoloBanchero13 小时前
Unity 虚拟仿真实验中设计模式的使用 ——状态模式(State Pattern)
unity·设计模式·状态模式
阿里巴巴中间件13 小时前
阿里云 AI 中间件重磅发布,打通 AI 应用落地“最后一公里”
人工智能·阿里云·中间件·云计算
SmalBox13 小时前
【光照】[PBR][镜面反射]实现方法解析
unity·渲染
Robbie丨Yang15 小时前
【Unity 入门教程】四、如何制作一个 Perfab
unity·游戏引擎
爱吃小胖橘16 小时前
Unity-动画IK控制
3d·unity·c#·游戏引擎