单机版网页启动程序
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

151 lines
3.6 KiB

using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Text;
using System.Threading;
using UnityEngine;
#if UNITY_2017_3_OR_NEWER
using UnityEngine.Networking;
#endif
namespace ZenFulcrum.EmbeddedBrowser {
/**
* Implements fetching BrowserAssets for standalone builds.
*
* During build, everything in BrowserAssets is packaged into a single file with the following format:
* brString {FileHeader}
* i32 numEntries
* {numEntries} IndexEntry objects
* data //The data section is a series of filedata chunks, as laid out in the index.
*/
public class StandaloneWebResources : WebResources {
public struct IndexEntry {
public string name;
public long offset;
public int length;
}
private const string FileHeader = "zfbRes_v1";
protected Dictionary<string, IndexEntry> toc = new Dictionary<string, IndexEntry>();
protected string dataFile;
public StandaloneWebResources(string dataFile) {
this.dataFile = dataFile;
}
public const string DefaultPath = "Resources/browser_assets";
public void LoadIndex() {
using (var data = new BinaryReader(File.OpenRead(dataFile))) {
var header = data.ReadString();
if (header != FileHeader) throw new Exception("Invalid web resource file");
var num = data.ReadInt32();
for (int i = 0; i < num; ++i) {
var entry = new IndexEntry() {
name = data.ReadString(),
offset = data.ReadInt64(),
length = data.ReadInt32(),
};
toc[entry.name] = entry;
}
}
}
public override void HandleRequest(int id, string url) {
var parsedURL = new Uri(url);
#if UNITY_2017_3_OR_NEWER
var path = UnityWebRequest.UnEscapeURL(parsedURL.AbsolutePath);
#else
var path = WWW.UnEscapeURL(parsedURL.AbsolutePath);
#endif
IndexEntry entry;
if (!toc.TryGetValue(path, out entry)) {
SendError(id, "Not found", 404);
return;
}
new Thread(() => {
try {
var ext = Path.GetExtension(entry.name);
if (ext.Length > 0) ext = ext.Substring(1);
string mimeType;
if (!extensionMimeTypes.TryGetValue(ext, out mimeType)) {
mimeType = extensionMimeTypes["*"];
}
using (var file = File.OpenRead(dataFile)) {
var pre = new ResponsePreamble {
headers = null,
length = entry.length,
mimeType = mimeType,
statusCode = 200,
};
SendPreamble(id, pre);
file.Seek(entry.offset, SeekOrigin.Begin);
var data = new byte[entry.length];
var readLen = file.Read(data, 0, entry.length);
if (readLen != data.Length) throw new Exception("Insufficient data for file");
SendData(id, data);
}
} catch (Exception ex) {
Debug.LogException(ex);
}
}).Start();
}
public void WriteData(Dictionary<string, byte[]> files) {
var entries = new Dictionary<string, IndexEntry>();
using (var file = File.OpenWrite(dataFile)) {
var writer = new BinaryWriter(file, Encoding.UTF8 /*, true (Mono too old)*/);
writer.Write(FileHeader);
writer.Write(files.Count);
var tocStart = file.Position;
foreach (var kvp in files) {
writer.Write(kvp.Key);
writer.Write(0L);
writer.Write(0);
}
//we'll come back and fill it in right later
foreach (var kvp in files) {
var data = kvp.Value;
var entry = new IndexEntry {
name = kvp.Key,
length = kvp.Value.Length,
offset = file.Position,
};
writer.Write(data);
entries[kvp.Key] = entry;
}
//now go back and write the correct data.
writer.Seek((int)tocStart, SeekOrigin.Begin);
foreach (var kvp in files) {
var entry = entries[kvp.Key];
writer.Write(kvp.Key);
writer.Write(entry.offset);
writer.Write(entry.length);
}
}
}
}
}