单机版网页启动程序
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.
 
 
 
 

226 lines
6.3 KiB

using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
namespace ZenFulcrum.EmbeddedBrowser {
/**
* Helper class for tracking and managing downloads.
* You can manage and handle downloads without this, but you may find it useful for dealing with the more
* common file downloading use cases.
*
* Usage: create one and call manager.ManageDownloads(browser) on a browser you want it to handle.
* or throw one in the scene and set "manageAllBrowsers" to true (before loading the scene) for it
* to automatically hook into all browsers that start in the scene.
*/
public class DownloadManager : MonoBehaviour {
[Tooltip("If true, this will find all the browser in the scene at startup and take control of their downloads.")]
public bool manageAllBrowsers = false;
[Tooltip("If true, a \"Save as\" style dialog will be given for all downloads.")]
public bool promptForFileNames;
[Tooltip("Where to save files. If null or blank, defaults to the user's downloads directory.")]
public string saveFolder;
[Tooltip("If given this text element will be updated with download status info.")]
public Text statusBar;
public class Download {
public Browser browser;
public int downloadId;
public string name;
public string path;
public int speed;
public int percent;
public string status;
}
public List<Download> downloads = new List<Download>();
public void Awake() {
if (manageAllBrowsers) {
foreach (var browser in FindObjectsOfType<Browser>()) {
ManageDownloads(browser);
}
}
}
public void ManageDownloads(Browser browser) {
browser.onDownloadStarted = (id, info) => {
HandleDownloadStarted(browser, id, info);
};
browser.onDownloadStatus += (id, info) => {
HandleDownloadStatus(browser, id, info);
};
}
private void HandleDownloadStarted(Browser browser, int downloadId, JSONNode info) {
//Debug.Log("Download requested: " + info.AsJSON);
var download = new Download {
browser = browser,
downloadId = downloadId,
name = info["suggestedName"],
};
if (promptForFileNames) {
browser.DownloadCommand(downloadId, BrowserNative.DownloadAction.Begin, null);
} else {
DirectoryInfo downloadFolder;
if (string.IsNullOrEmpty(saveFolder)) {
downloadFolder = new DirectoryInfo(GetUserDownloadFolder());
} else {
downloadFolder = new DirectoryInfo(saveFolder);
if (!downloadFolder.Exists) downloadFolder.Create();
}
var filePath = downloadFolder.FullName + "/" + new FileInfo(info["suggestedName"]).Name;
while (File.Exists(filePath)) {
var ext = Path.GetExtension(filePath);
var left = Path.GetFileNameWithoutExtension(filePath);
var time = DateTime.Now.ToString("yyyy-MM-dd hh_mm_ss");
filePath = downloadFolder.FullName + "/" + left + " " + time + ext;
}
browser.DownloadCommand(downloadId, BrowserNative.DownloadAction.Begin, filePath);
}
downloads.Add(download);
}
private void HandleDownloadStatus(Browser browser, int downloadId, JSONNode info) {
//Debug.Log("Download status: " + info.AsJSON);
for (int i = 0; i < downloads.Count; i++) {
if (downloads[i].browser != browser || downloads[i].downloadId != downloadId) continue;
var download = downloads[i];
download.status = info["status"];
download.speed = info["speed"];
download.percent = info["percentComplete"];
if (!string.IsNullOrEmpty(info["fullPath"])) download.name = Path.GetFileName(info["fullPath"]);
break;
}
}
public void Update() {
if (statusBar) {
statusBar.text = Status;
}
}
public void PauseAll() {
for (int i = 0; i < downloads.Count; i++) {
if (downloads[i].status == "working") {
downloads[i].browser.DownloadCommand(downloads[i].downloadId, BrowserNative.DownloadAction.Pause);
}
}
}
public void ResumeAll() {
for (int i = 0; i < downloads.Count; i++) {
if (downloads[i].status == "working") {
downloads[i].browser.DownloadCommand(downloads[i].downloadId, BrowserNative.DownloadAction.Resume);
}
}
}
public void CancelAll() {
for (int i = 0; i < downloads.Count; i++) {
if (downloads[i].status == "working") {
downloads[i].browser.DownloadCommand(downloads[i].downloadId, BrowserNative.DownloadAction.Cancel);
}
}
}
public void ClearAll() {
CancelAll();
downloads.Clear();
}
private StringBuilder sb = new StringBuilder();
/** Returns a string summarizing things that are downloading. */
public string Status {
get {
if (downloads.Count == 0) return "";
sb.Length = 0;
var rate = 0;
for (int i = downloads.Count - 1; i >= 0; i--) {
if (sb.Length > 0) sb.Append(", ");
sb.Append(downloads[i].name);
if (downloads[i].status == "working") {
if (downloads[i].percent >= 0) sb.Append(" (").Append(downloads[i].percent).Append("%)");
else sb.Append(" (??%)");
rate += downloads[i].speed;
} else {
sb.Append(" (").Append(downloads[i].status).Append(")");
}
}
var ret = "Downloads";
if (rate > 0) {
ret += " (" + Mathf.Round(rate / (1024f * 1024) * 100) / 100f + "MiB/s)";
}
return ret + ": " + sb.ToString();
}
}
/** Gets the user's download folder, creating it if needed. */
public static string GetUserDownloadFolder() {
switch (System.Environment.OSVersion.Platform) {
case PlatformID.Win32NT: {
IntPtr path;
var r = SHGetKnownFolderPath(
new Guid("{374DE290-123F-4565-9164-39C4925E467B}"), //downloads
0x8000, //KF_FLAG_CREATE
IntPtr.Zero, //current user
out path
);
if (r == 0) {
var ret = Marshal.PtrToStringUni(path);
Marshal.FreeCoTaskMem(path);
return ret;
} else {
throw new Exception(
"Failed to get user download directory",
new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error())
);
}
}
case PlatformID.Unix: {
var path = System.Environment.GetEnvironmentVariable("HOME") + "/Downloads";
var di = new DirectoryInfo(path);
if (!di.Exists) di.Create();
return path;
}
case PlatformID.MacOSX:
throw new NotImplementedException();
default:
throw new NotImplementedException();
}
}
[DllImport("Shell32.dll")]
private static extern int SHGetKnownFolderPath(
[MarshalAs(UnmanagedType.LPStruct)]Guid rfid, uint dwFlags, IntPtr hToken,
out IntPtr ppszPath
);
}
}