Update
This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Networking;
|
||||
|
||||
namespace DA_Assets.Networking
|
||||
{
|
||||
public class RequestSender
|
||||
{
|
||||
public static async Task<Texture2D> LoadImage(string url)
|
||||
{
|
||||
using (UnityWebRequest webRequest = UnityWebRequestTexture.GetTexture(url))
|
||||
{
|
||||
var asyncOp = webRequest.SendWebRequest();
|
||||
|
||||
while (!asyncOp.isDone)
|
||||
{
|
||||
await Task.Yield();
|
||||
}
|
||||
|
||||
bool isRequestError;
|
||||
#if UNITY_2020_1_OR_NEWER
|
||||
isRequestError = webRequest.result != UnityWebRequest.Result.Success;
|
||||
#else
|
||||
isRequestError = webRequest.isNetworkError || webRequest.isHttpError;
|
||||
#endif
|
||||
|
||||
if (isRequestError)
|
||||
{
|
||||
Debug.LogError($"LoadImage | {webRequest.error}");
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
Texture2D texture = DownloadHandlerTexture.GetContent(webRequest);
|
||||
return texture;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task<string> Get(string url, int awaitDelayMs = 100)
|
||||
{
|
||||
using (UnityWebRequest webRequest = UnityWebRequest.Get(url))
|
||||
{
|
||||
try
|
||||
{
|
||||
#if UNITY_6000_0_OR_NEWER
|
||||
await webRequest.SendWebRequest();
|
||||
#else
|
||||
webRequest.SendWebRequest();
|
||||
|
||||
while (!webRequest.isDone)
|
||||
await Task.Delay(awaitDelayMs);
|
||||
#endif
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogException(ex);
|
||||
return null;
|
||||
}
|
||||
|
||||
bool isRequestError;
|
||||
#if UNITY_2020_1_OR_NEWER
|
||||
isRequestError = webRequest.result != UnityWebRequest.Result.Success;
|
||||
#else
|
||||
isRequestError = webRequest.isNetworkError || webRequest.isHttpError;
|
||||
#endif
|
||||
|
||||
if (isRequestError)
|
||||
{
|
||||
Debug.LogError($"RequestSender.Get | {webRequest.error}");
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
string result = webRequest.downloadHandler.text;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task<string> Post(string url, string postData, string contentType, Dictionary<string, string> headers = null, int awaitDelayMs = 100)
|
||||
{
|
||||
using (UnityWebRequest webRequest = new UnityWebRequest(url, "POST"))
|
||||
{
|
||||
byte[] bodyRaw = Encoding.UTF8.GetBytes(postData);
|
||||
webRequest.uploadHandler = new UploadHandlerRaw(bodyRaw);
|
||||
webRequest.downloadHandler = new DownloadHandlerBuffer();
|
||||
webRequest.SetRequestHeader("Content-Type", contentType);
|
||||
|
||||
if (headers != null)
|
||||
{
|
||||
foreach (var header in headers)
|
||||
{
|
||||
webRequest.SetRequestHeader(header.Key, header.Value);
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
#if UNITY_6000_0_OR_NEWER
|
||||
await webRequest.SendWebRequest();
|
||||
#else
|
||||
webRequest.SendWebRequest();
|
||||
|
||||
while (!webRequest.isDone)
|
||||
await Task.Delay(awaitDelayMs);
|
||||
#endif
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogException(ex);
|
||||
return null;
|
||||
}
|
||||
|
||||
while (!webRequest.isDone)
|
||||
await Task.Delay(awaitDelayMs);
|
||||
|
||||
bool isRequestError;
|
||||
#if UNITY_2020_1_OR_NEWER
|
||||
isRequestError = webRequest.result != UnityWebRequest.Result.Success;
|
||||
#else
|
||||
isRequestError = webRequest.isNetworkError || webRequest.isHttpError;
|
||||
#endif
|
||||
|
||||
if (isRequestError)
|
||||
{
|
||||
string methodPath = $"{nameof(RequestSender)}.{nameof(Post)}";
|
||||
Debug.LogError($"{methodPath} | Error: {webRequest.error}");
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
string result = webRequest.downloadHandler.text;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dce7cba30a6eedc46a3f8fbd927f8035
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,230 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace DA_Assets.Networking
|
||||
{
|
||||
public class UnityHttpClient : IDisposable
|
||||
{
|
||||
private readonly HttpClient _httpClient;
|
||||
private HttpRequestMessage _requestMessage;
|
||||
private CancellationTokenSource _cancellationTokenSource;
|
||||
|
||||
public DownloadHandler downloadHandler { get; private set; }
|
||||
public long downloadedBytes { get; private set; }
|
||||
public float downloadProgress { get; private set; }
|
||||
public string error { get; private set; }
|
||||
public bool isDone { get; private set; }
|
||||
public HttpStatusCode responseCode { get; private set; }
|
||||
public WR_Result result { get; private set; }
|
||||
|
||||
private UnityHttpClient(HttpMethod method, string url, HttpContent content = null)
|
||||
{
|
||||
_httpClient = new HttpClient
|
||||
{
|
||||
Timeout = TimeSpan.FromMinutes(5)
|
||||
};
|
||||
|
||||
_requestMessage = new HttpRequestMessage(method, url);
|
||||
|
||||
if (content != null)
|
||||
{
|
||||
_requestMessage.Content = content;
|
||||
}
|
||||
|
||||
downloadHandler = new DownloadHandler();
|
||||
downloadedBytes = 0;
|
||||
error = string.Empty;
|
||||
isDone = false;
|
||||
responseCode = 0;
|
||||
result = WR_Result.InProgress;
|
||||
downloadProgress = 0f;
|
||||
}
|
||||
|
||||
public static UnityHttpClient Get(string url)
|
||||
{
|
||||
return new UnityHttpClient(HttpMethod.Get, url);
|
||||
}
|
||||
|
||||
public static UnityHttpClient Post(string url, WWWForm form)
|
||||
{
|
||||
var content = new ByteArrayContent(form.data);
|
||||
foreach (var header in form.headers)
|
||||
{
|
||||
content.Headers.Add(header.Key, header.Value);
|
||||
}
|
||||
return new UnityHttpClient(HttpMethod.Post, url, content);
|
||||
}
|
||||
|
||||
public void SetRequestHeader(string name, string value)
|
||||
{
|
||||
if (_requestMessage.Headers.Contains(name))
|
||||
{
|
||||
_requestMessage.Headers.Remove(name);
|
||||
}
|
||||
_requestMessage.Headers.Add(name, value);
|
||||
}
|
||||
|
||||
public async Task SendWebRequest(CancellationTokenSource cancellationTokenSource = null)
|
||||
{
|
||||
if (cancellationTokenSource == null)
|
||||
{
|
||||
_cancellationTokenSource = new CancellationTokenSource();
|
||||
}
|
||||
else
|
||||
{
|
||||
_cancellationTokenSource = cancellationTokenSource;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
using (HttpResponseMessage response = await _httpClient.SendAsync(
|
||||
_requestMessage,
|
||||
HttpCompletionOption.ResponseHeadersRead,
|
||||
_cancellationTokenSource.Token).ConfigureAwait(false))
|
||||
{
|
||||
responseCode = response.StatusCode;
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
var contentLength = response.Content.Headers.ContentLength;
|
||||
using (var responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false))
|
||||
using (var memoryStream = new MemoryStream())
|
||||
{
|
||||
if (contentLength.HasValue)
|
||||
{
|
||||
Progress<long> progress = new Progress<long>(totalBytes =>
|
||||
{
|
||||
downloadedBytes = totalBytes;
|
||||
downloadProgress = (float)downloadedBytes / contentLength.Value;
|
||||
});
|
||||
await responseStream.CopyToAsync(memoryStream, 81920, progress, _cancellationTokenSource.Token).ConfigureAwait(false);
|
||||
downloadProgress = 1f;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if UNITY_2021_3_OR_NEWER
|
||||
await responseStream.CopyToAsync(memoryStream, _cancellationTokenSource.Token).ConfigureAwait(false);
|
||||
#else
|
||||
await responseStream.CopyToAsync(memoryStream).ConfigureAwait(false);
|
||||
#endif
|
||||
downloadProgress = -1f;
|
||||
}
|
||||
|
||||
byte[] data = memoryStream.ToArray();
|
||||
Encoding encoding = Encoding.UTF8;
|
||||
string charset = response.Content.Headers.ContentType?.CharSet;
|
||||
|
||||
if (!string.IsNullOrEmpty(charset))
|
||||
{
|
||||
try
|
||||
{
|
||||
encoding = Encoding.GetEncoding(charset);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
}
|
||||
var text = encoding.GetString(data);
|
||||
downloadHandler.SetData(data);
|
||||
downloadHandler.SetText(text);
|
||||
result = WR_Result.Success;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string errorMessage = $"Error: {response.StatusCode}";
|
||||
downloadHandler.SetError(errorMessage);
|
||||
error = errorMessage;
|
||||
result = WR_Result.ProtocolError;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
downloadHandler.SetError(ex.Message);
|
||||
error = ex.Message;
|
||||
result = WR_Result.ConnectionError;
|
||||
}
|
||||
finally
|
||||
{
|
||||
isDone = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_requestMessage?.Dispose();
|
||||
_httpClient?.Dispose();
|
||||
_cancellationTokenSource?.Cancel();
|
||||
_cancellationTokenSource?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// https://stackoverflow.com/a/46497896
|
||||
/// </summary>
|
||||
public static class StreamExtensions
|
||||
{
|
||||
public static async Task CopyToAsync(this Stream source, Stream destination, int bufferSize, IProgress<long> progress = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (source == null)
|
||||
throw new ArgumentNullException(nameof(source));
|
||||
if (!source.CanRead)
|
||||
throw new ArgumentException("Has to be readable", nameof(source));
|
||||
if (destination == null)
|
||||
throw new ArgumentNullException(nameof(destination));
|
||||
if (!destination.CanWrite)
|
||||
throw new ArgumentException("Has to be writable", nameof(destination));
|
||||
if (bufferSize < 0)
|
||||
throw new ArgumentOutOfRangeException(nameof(bufferSize));
|
||||
|
||||
var buffer = new byte[bufferSize];
|
||||
long totalBytesRead = 0;
|
||||
int bytesRead;
|
||||
while ((bytesRead = await source.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false)) != 0)
|
||||
{
|
||||
await destination.WriteAsync(buffer, 0, bytesRead, cancellationToken).ConfigureAwait(false);
|
||||
totalBytesRead += bytesRead;
|
||||
progress?.Report(totalBytesRead);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class DownloadHandler
|
||||
{
|
||||
public byte[] data { get; private set; }
|
||||
public string text { get; private set; }
|
||||
public string error { get; private set; }
|
||||
|
||||
public void SetData(byte[] data)
|
||||
{
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public void SetText(string text)
|
||||
{
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public void SetError(string error)
|
||||
{
|
||||
this.error = error;
|
||||
}
|
||||
|
||||
public bool HasError => !string.IsNullOrEmpty(error);
|
||||
}
|
||||
|
||||
public enum WR_Result
|
||||
{
|
||||
InProgress,
|
||||
Success,
|
||||
ConnectionError,
|
||||
ProtocolError,
|
||||
DataProcessingError
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d750e6243861193479aca4fe9486e373
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user