TLabAltoh / TLabWebViewVR-OculusIntegration-2022

This sample is the minimum configuration for using TLabWebView with the MetaXR SDK.
https://tlabgames.gitbook.io/tlabwebview/
2 stars 0 forks source link

Handle file download with Unity instead of native plugin #2

Open iliasmal opened 3 weeks ago

iliasmal commented 3 weeks ago

Hello. Thank you very much for this asset. I have only one question. Is it possible to handle any file download inside Unity and not through the native plugin? Or, can I have in Unity the download link that I click on inside WebView?

Thank you in advance.

TLabAltoh commented 3 weeks ago

Just a few minutes ago, I added a function to catch download url and function to request file download from the C#.

Code Sample (C#) ```.cs // This component is attached to the game object name of Download Event Test. // https://github.com/TLabAltoh/TLabWebView/blob/master/Runtime/Test/DownloadEventTest.cs [SerializeField] private TLabWebView m_webview; // Get Download Event's Parameters from Webview public void OnCatchDownloadUrl(string argument) { var commands = argument.Split("\n"); var url = commands[0]; var userAgent = commands[1]; var contentDisposition = commands[2]; var mimeType = commands[3]; Debug.Log(THIS_NAME + $"message receive: catch download url ... url:{url}, userAgent:{userAgent}, contentDisposition:{contentDisposition}, mimeType:{mimeType}"); // request file download (You can choose whether or not to download) m_webview.DownloadFromUrl(url, userAgent, contentDisposition, mimeType); } ```

inspector-settings

If you want to download a file with a pure C# implementation, you may find UnityWebRequest useful.

iliasmal commented 3 weeks ago

Thank you for your quick answer.Everything works fine! I have one problem, though, and I don't know how to tackle it. When I get the download url, it points to a blob (blob:https://dddd.com/hgdjhsd-asdasdasd- and so on). How can I read the bytes of this? I know this hasn't anything to do with your work, but I hope if you could point me to the right direction...

Thank you again!

TLabAltoh commented 3 weeks ago

To read file data from the blob url, you need to get a base64 string from the blob url. you can get file byte data from base64 string. Here is a sample code.

Get base64 from blob url ```.cs [SerializeField] private TLabWebView m_webview; public void GetBase64FromBlobUrlCallback(string url) { // message receive: data:text/plain;base64,SGVsbG8sIHdvcmxkIQ== // SGVsbG8sIHdvcmxkIQ== is the Base64 encoding of "Hello, world!" Debug.Log(THIS_NAME + $"message receive: {url}"); } public void GetBase64FromBlobUrl(string url, string mimeType) { string js = "var xhr = new XMLHttpRequest();" + "xhr.open('GET', '" + url + "', true);" + "xhr.setRequestHeader('Content-type','" + mimeType + ";charset=UTF-8');" + "xhr.responseType = 'blob';" + "xhr.onload = function(e) {" + " if (this.status == 200) {" + " var blobFile = this.response;" + " var reader = new FileReader();" + " reader.readAsDataURL(blobFile);" + " reader.onloadend = function() {" + " base64data = reader.result;" + " window.TLabWebViewActivity.unitySendMessage('" + this.gameObject.name + "','GetBase64FromBlobUrlCallback', base64data);" + " }" + " }" + "};" + "xhr.send();"; m_webview.EvaluateJS(js); } public void OnCatchDownloadUrl(string argument) { var commands = argument.Split("\n"); var url = commands[0]; var userAgent = commands[1]; var contentDisposition = commands[2]; var mimeType = commands[3]; if (url.StartsWith("blob:")) { GetBase64FromBlobUrl(url, mimeType); } } ```
iliasmal commented 3 weeks ago

Thank you again!!! I have tried the code and it closes (crashes) the app when it sends the unitySendMessge. If I replace base64data with a string, everything works ok (I mean the callback works.). I have tried many things in the js call, but nothing seems to work. I have even tried to override the mime type and change the responseType, but nothing happened... Do you have any ideas?

TLabAltoh commented 3 weeks ago

Sorry for late reply, this problem because Java cause stack overflow when pass the too large string (like image file), I'm currently implementing map string buffer to memory and send pointer to C# ...

iliasmal commented 3 weeks ago

That will be great! Thank you for your time and effort!

TLabAltoh commented 3 weeks ago

In the latest update I added a sample to get base64 string from blob url and map base64 string to java's ByteBuffer. It can also be accessed from the C# side, but at the moment it can't be accessed with a pointer, but it can avoid an app crash (stack overflow) with a 3000KB file. Note that the mapped buffers contain the data url scheme in the head (like "data:...."). And if the mapped data return to C# is wrong, please let me know.

Get base64 from blob URL ```.cs // https://github.com/TLabAltoh/TLabWebView/blob/master/Runtime/Test/DownloadEventTest.cs [SerializeField] private TLabWebView m_webview; private string THIS_NAME => "[dltest] "; public void BlobToDataUrlCallback(string argument) { var commands = argument.Split("\n"); var bufferName = commands[0]; var mimeType = commands[1]; Debug.Log(THIS_NAME + $"message receive: {bufferName}, {mimeType}"); // data:[][;base64], byte[] buf = m_webview.GetWebBuffer(bufferName); //Debug.Log(THIS_NAME + $"message receive: {buf[0]}, {buf[1]}, {buf[2]}, {buf[3]}, {buf[4]}, length: {buf.Length}"); // data: //Debug.Log(THIS_NAME + $"message receive: {buf[buf.Length - 1]}, {buf[3999999]}, {buf[4000000]}, {buf[4000001]}, {buf[4000002]}, {buf[4500]}, {buf[100]}, {buf[600]}, {buf[500]}"); string js = $"window.TLabWebViewActivity.free('{bufferName}');"; m_webview.EvaluateJS(js); } public void BlobToDataUrl(string url, string mimeType) { // https://developer.mozilla.org/ja/docs/Web/API/FileReader/readAsDataURL string js = "function writeBuffer(buffer, bufferName, segmentSize, offset)" + "{" + " if (segmentSize === 0) return;" + "" + " var i = offset;" + " while(i + segmentSize <= buffer.length)" + " {" + " window.TLabWebViewActivity.write(bufferName, buffer.slice(i, i + segmentSize));" + " i += segmentSize" + " }" + "" + " writeBuffer(buffer, bufferName, parseInt(segmentSize / 2), i);" + "}" + "var xhr = new XMLHttpRequest();" + "xhr.open('GET', '" + url + "', true);" + "xhr.setRequestHeader('Content-type','" + mimeType + ";charset=UTF-8');" + "xhr.responseType = 'blob';" + "xhr.onload = function(e) {" + " if (this.status == 200) {" + " var blobFile = this.response;" + " var reader = new FileReader();" + " reader.readAsDataURL(blobFile);" + " reader.onloadend = function() {" + " base64data = reader.result;" + " bufferName = 'data-url';" + " buffer = new TextEncoder().encode(base64data);" + " window.TLabWebViewActivity.malloc(bufferName, buffer.length);" + " writeBuffer(buffer, bufferName, 500000, 0);" + " window.TLabWebViewActivity.unitySendMessage('" + this.gameObject.name + "','BlobToDataUrlCallback', bufferName + '\\n' + '" + mimeType + "');" + " }" + " }" + "};" + "xhr.send();"; m_webview.EvaluateJS(js); } public void OnCatchDownloadUrl(string argument) { var commands = argument.Split("\n"); var url = commands[0]; var userAgent = commands[1]; var contentDisposition = commands[2]; var mimeType = commands[3]; Debug.Log(THIS_NAME + $"message receive: catch download url ... url:{url}, userAgent:{userAgent}, contentDisposition:{contentDisposition}, mimeType:{mimeType}"); if (url.StartsWith("blob:")) { BlobToDataUrl(url, mimeType); } else { m_webview.DownloadFromUrl(url, userAgent, contentDisposition, mimeType); } } ```
iliasmal commented 2 weeks ago

My files are well over 5mbs, but I will try.

Thank you!