unity打包web平台选择本地文件并上传

unity打包web平台选择本地文件并上传

  • 沙盒:浏览器的安全机制,浏览器内的进程不能直接访问本地计算机中的硬盘等硬件或数据。必须通过js作为中间层实现。
  • 需求:通过一个按钮,点击后选择文件传到webgl进程中。
  • 前置说明:需要有webgl模版等基础配备,已经可以发布webgl程序。
mergeInto(LibraryManager.library, 
{
        LoadFile:function (gameobjectName,fitter) {
            var gameobjectNameStr=Pointer_stringify(gameobjectName);
            var fitterStr=Pointer_stringify(fitter);
            console.log("GetSelectFileURL");
            console.log("需要被发送的物体名称转化:");
            console.log(gameobjectNameStr);
            
            console.log("需要筛选文件类型转化:");
            console.log(fitterStr);
            var fileInput = document.getElementById("load");//通过id获取创建好的input元素
            if(!fileInput){
                var fileInput = document.createElement('input');//创建input元素
                console.log("创建input元素");
                fileInput.setAttribute('id', "load");//给创建的input设置id
                
                fileInput.setAttribute('type', 'file');
                fileInput.setAttribute('style','display:none;');
                fileInput.setAttribute('style','visibility:hidden;'); 
                fileInput.setAttribute('multiple', '');
                fileInput.disabled=true;//使input元素不可点击,否则会导致页面上所有位置都可唤起文件对话框
                document.body.appendChild(fileInput);
            }
            
            fileInput.accept=fitterStr;
            fileInput.disabled=false;//设置input可点击,否则无法通过click()打开文件对话框
            fileInput.click()//打开文件对话框
            fileInput.onclick = function (event) {
                this.value = null;
            };
            fileInput.onchange = function (event) {
               //如果需要在unity中获取文件内容,在onchange中获取后通过SendMessage()传回给unity
               var files = event.target.files;
               questPost(files);//index中上传
               //var res={
                    //Path:URL.createObjectURL(files[0]),
                    //FileName:files[0].name
               //};
               //gameInstance.SendMessage(gameobjectNameStr, 'FileDialogResult', JSON.stringify(res));
            }
            document.onmouseup = function() {
                fileInput.click();
                document.onmouseup = null;
            }
            fileInput.disabled=true;//结束时再次设置input不可点击,保证点击其他位置无法打开文件对话框
            //确保只有点击按钮2时才能打开文件对话框
            
        },
});

代码说明

该js脚本中,LoadFile函数名,接收一个游戏物体名称和过滤文件格式字符串。

游戏物体名称用于在该js函数中发送广播,叫该游戏物体执行指定挂在在该物体mono脚本上的指定方法。

注意:所有C#传给js的字符串都需要用Pointer_stringify过一遍,才能转化成js识别的字符串。

主要逻辑为:js动态创建一个元素,设置交互属性,定义选择文件事件函数,在函数内部用:

gameInstance.SendMessage(gameobjectNameStr, 'FileDialogResult', JSON.stringify(res));

其中,gameInstance是unity运行实例,有的叫unityInstance或者别的东西,具体看自己js模版中定义的变量。gameobjectNameStr:转化过后的游戏物体名称;FileDialogResult:游戏物体上的需要被执行的函数;JSON.stringify(res):该函数接收的一个参数,这里我封装为一个json对象可以传递多个参数,传过去后解析为一个文件信息类。

调用

    public class JSFileInfo
    {
        public string Path { get; set; }
        public string FileName { get; set; }
    }
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using Newtonsoft.Json;
using UnityEngine;
using UnityEngine.Networking;
 
public class LoadExlBtn : MonoBehaviour
{
    public string fileFullPath;
 
    [DllImport("__Internal")]
    private static extern void LoadFile(string gameobjectName,string fitter);
    
    public void Add_File()
    {
        if (Application.platform == RuntimePlatform.WebGLPlayer)
        {
            LoadFile(gameObject.name,".xls,.xlsx");//web端调用方法
        }
    }
    
    public void FileDialogResult(string JsFileInfoStr)
    {
        Debug.Log(JsFileInfoStr);
        JSFileInfo jsFileInfo = JsonConvert.DeserializeObject<JSFileInfo>(JsFileInfoStr);
        Debug.Log(jsFileInfo.Path);
        Debug.Log(jsFileInfo.FileName);
        StartCoroutine(LoadData(jsFileInfo,null));
    }
 
    IEnumerator LoadData(JSFileInfo jsFileInfo,Action<FileStream> action)
    {
        UnityWebRequest request = UnityWebRequest.Get(jsFileInfo.Path);
        //创建文件夹
        string dirPath = Path.Combine(Application.persistentDataPath, "Exls");
        Debug.Log("将被存至目录:"+dirPath);
        if (!Directory.Exists(dirPath))
        {
            Directory.CreateDirectory(dirPath);
        }
        string fullPath = Path.Combine(dirPath, jsFileInfo.FileName);
        request.downloadHandler = new DownloadHandlerFile(fullPath);//路径+文件名
 
        Debug.Log("复制到沙盒ing");
        yield return request.SendWebRequest();
        if (request.result==UnityWebRequest.Result.Success)
        {
            Debug.Log("复制到沙盒完成");
 
            fileFullPath = fullPath;
            FileStream fs = new FileStream(fullPath, FileMode.Open);
            Debug.Log(fs.Length);//byte
            Debug.Log(fs.Name);//路径+名
 
            if (action!=null)
            {
                action(fs);
            }
            fs.Close();
 
            FileInfo f = new FileInfo(fullPath);
            Debug.Log(f.Name);
        }else
        {
            Debug.Log(request.error);
        }  
        
 
    }
 
}

主要逻辑:

  • 编辑器中添加按钮监听Add_File()
  • 调用外部js中的LoadFile,传入本按钮名称、文件过滤格式。
  • 在js中创建点击元素,模拟点击,获取文件对于浏览器沙盒来说的url(是blob:xxx的形式),广播消息给这个按钮的FileDialogResult。
  • 在FileDialogResult中开协程用UnityWebRequest将文件存到浏览器沙盒中的persistentDataPath。
    (如果是图片文字等简单的东西可以不用存为实体文件,直接用api)

根据原文补充内容

<!DOCTYPE html>
<html lang="en-us">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>Unity WebGL Player | LoadModelTest</title>
    <link rel="shortcut icon" href="TemplateData/favicon.ico">
    <link rel="stylesheet" href="TemplateData/style.css">
  </head>
  <body>
    <div id="unity-container" class="unity-desktop">
      <canvas id="unity-canvas" width=960 height=600></canvas>
      <div id="unity-loading-bar">
        <div id="unity-logo"></div>
        <div id="unity-progress-bar-empty">
          <div id="unity-progress-bar-full"></div>
        </div>
      </div>
      <div id="unity-warning"> </div>
      <div id="unity-footer">
        <div id="unity-webgl-logo"></div>
        <div id="unity-fullscreen-button"></div>
        <div id="unity-build-title">LoadModelTest</div>
      </div>
    </div>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    <script>
      var container = document.querySelector("#unity-container");
      var canvas = document.querySelector("#unity-canvas");
      var loadingBar = document.querySelector("#unity-loading-bar");
      var progressBarFull = document.querySelector("#unity-progress-bar-full");
      var fullscreenButton = document.querySelector("#unity-fullscreen-button");
      var warningBanner = document.querySelector("#unity-warning");
      
      function questPost(files){
        const file = files[0];
               const formData = new FormData();
               formData.append('file', file);
               axios.post('/dev-api/file/upload', formData, {
               headers: {
               'Content-Type': 'multipart/form-data',
               '我是的头肯的头头':'我是头肯本人',
               }
               })
               .then(response => {
               console.log('File uploaded successfully',response);
               unityInstanceOne.SendMessage("GameObject","FileDialogResult",response.data.data.url)//回传返回消息
               // 处理响应数据
               })
               .catch(error => {
               console.error('Error uploading file');
               // 处理错误情况
               });
      }
      function unityShowBanner(msg, type) {
        function updateBannerVisibility() {
          warningBanner.style.display = warningBanner.children.length ? 'block' : 'none';
        }
        var div = document.createElement('div');
        div.innerHTML = msg;
        warningBanner.appendChild(div);
        if (type == 'error') div.style = 'background: red; padding: 10px;';
        else {
          if (type == 'warning') div.style = 'background: yellow; padding: 10px;';
          setTimeout(function() {
            warningBanner.removeChild(div);
            updateBannerVisibility();
          }, 5000);
        }
        updateBannerVisibility();
      }

      var buildUrl = "Build";
      var loaderUrl = buildUrl + "/webbuild0524.3.loader.js";
      var config = {
        dataUrl: buildUrl + "/webbuild0524.3.data.unityweb",
        frameworkUrl: buildUrl + "/webbuild0524.3.framework.js.unityweb",
        codeUrl: buildUrl + "/webbuild0524.3.wasm.unityweb",
        streamingAssetsUrl: "StreamingAssets",
        companyName: "DefaultCompany",
        productName: "LoadModelTest",
        productVersion: "0.1",
        showBanner: unityShowBanner,
      };

      // By default Unity keeps WebGL canvas render target size matched with
      // the DOM size of the canvas element (scaled by window.devicePixelRatio)
      // Set this to false if you want to decouple this synchronization from
      // happening inside the engine, and you would instead like to size up
      // the canvas DOM size and WebGL render target sizes yourself.
      // config.matchWebGLToCanvasSize = false;

      if (/iPhone|iPad|iPod|Android/i.test(navigator.userAgent)) {
        container.className = "unity-mobile";
        // Avoid draining fillrate performance on mobile devices,
        // and default/override low DPI mode on mobile browsers.
        config.devicePixelRatio = 1;
        unityShowBanner('WebGL builds are not supported on mobile devices.');
      } else {
        canvas.style.width = "960px";
        canvas.style.height = "600px";
      }
      loadingBar.style.display = "block";

      var script = document.createElement("script");
      script.src = loaderUrl;
      script.onload = () => {
        createUnityInstance(canvas, config, (progress) => {
          progressBarFull.style.width = 100 * progress + "%";
        }).then((unityInstance) => {
          loadingBar.style.display = "none";
          unityInstanceOne = unityInstance
        }).catch((message) => {
          alert(message);
        });
      };
      document.body.appendChild(script);
    </script>
  </body>
</html>

原文链接:https://blog.csdn.net/love_c_s/article/details/135666003

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值