satanas / unity-simple-http Goto Github PK
View Code? Open in Web Editor NEWA dead simple HTTP client for Unity3D
License: Other
A dead simple HTTP client for Unity3D
License: Other
Assets/SimpleHTTP/Client.cs(39,22): warning CS0618: UnityEngine.Networking.UnityWebRequest.Send()' is obsolete:
Use SendWebRequest. It returns a UnityWebRequestAsyncOperation which contains a reference to the WebRequest object.'
public FormData AddField(string name, byte[] rawData, string fileName, string contentType)
{
formData.Add(new MultipartFormFileSection(name, rawData, fileName, contentType));
return this;
}
needed this for properly uploading a file to my server without it i was getting error 500
eg:
string[] files = Directory.GetFiles(@"Assets\Resources\Files");
foreach(var f in files)
{
Debug.Log(f);
}
Byte[] aFile = File.ReadAllBytes(files[2]);
string val = Encoding.UTF8.GetString(aFile);
FormData formData = new FormData()
.AddField("Title", "TestUpload2")
.AddField("Bytes", aFile, "Test.jpg", "image/jpg");
A while ago, I tested our project's error handling by completely disconnecting my computer from internet. In this scenario, all responses returned by SimpleHTTP would be null; I just accepted this was its way of saying "Server did not respond" and made sure to catch it.
However right now, we've been facing responses that are not null, but still came with an empty body a,d a Status Code of 0, and all other sources I found say that 0 is also what usually means that the server did not respond.
I'm still trying to figure out what causes these Status 0 to happen, so I'd like to know, what is the difference between a null response and a response with Status 0 ?
To build and parse URLs, query params, etc
Some of the events that may be propagated:
For URLs, bodies, headers, and parameters in general
Would be nice if we could add those new webrequest features.
I have somethin g i did work on in the past, would be nice to hook it up within your wrapper.
` class FileDownloadHandler : DownloadHandlerScript
{
private int expected = -1;
private int received = 0;
private string filepath;
private FileStream fileStream;
private bool canceled = false;
public FileDownloadHandler(byte[] buffer, string filepath) : base(buffer)
{
this.filepath = filepath;
fileStream = new FileStream(filepath, FileMode.Create, FileAccess.Write);
}
protected override byte[] GetData()
{
return null;
}
protected override bool ReceiveData(byte[] data, int dataLength)
{
if (data == null || data.Length < 1)
{
return false;
}
received += dataLength;
if (!canceled)
{
fileStream.Write(data, 0, dataLength);
}
return true;
}
protected override float GetProgress()
{
if (expected < 0)
{
return 0;
}
return (float)received / expected;
}
protected override void CompleteContent()
{
fileStream.Close();
}
protected override void ReceiveContentLength(int contentLength)
{
expected = contentLength;
}
public void Cancel()
{
canceled = true;
fileStream.Close();
File.Delete(filepath);
}
}`
`public class Downloader
{
public event Action OnBegin;
public event Action OnComplete;
public event Action OnProgress;
public event Action OnError;
// public Text bytesText;
private float progress;
//public Text response;
private string cachedfromJson;
public List<UnityWebRequest> requests = new List<UnityWebRequest>();
private bool needDeleting = false;
public long ContentLength
{
get;
private set;
}
public static string GeneralDevicePath
{
get
{
string path = Application.persistentDataPath + "/Data/";
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
return path;
}
}
public static string DeviceAssetsPath
{
get
{
string result = GeneralDevicePath + "Assets/";
if (!Directory.Exists(result))
{
Directory.CreateDirectory(result);
}
return result;
}
}
public static string DeviceDatabasePath
{
get
{
string result = DeviceAssetsPath + "Content/";
if (!Directory.Exists(result))
{
Directory.CreateDirectory(result);
}
return result;
}
}
public string CachedValue
{
get
{
return cachedfromJson;
}
set
{
cachedfromJson = value;
}
}
public IEnumerator GetAppData(Guid appBuilderId)
{
string appBuilderUrlFormat = AppData.ApplicationJSONUrl;
string jsonUrl = string.Format(appBuilderUrlFormat, appBuilderId);
string jsonPath = string.Format(@"{0}/{1}.json", Application.persistentDataPath, appBuilderId);
using (UnityWebRequest www = new UnityWebRequest(jsonUrl + "?=" + Guid.NewGuid(), UnityWebRequest.kHttpVerbGET))
{
byte[] buffer = new byte[64 * 1024];
www.SetRequestHeader("Cache-Control", "max-age=0, no-cache, no-store");
www.SetRequestHeader("Pragma", "no-cache");
www.downloadHandler = new FileDownloadHandler(buffer, jsonPath);
www.SendWebRequest();
while (!www.isDone)
{
yield return www;
}
if (www.isNetworkError || www.isHttpError)
{
long responseCode = www.responseCode;
Debug.Log(string.Format("request {0} error {1}", jsonUrl, www.error));
//response.text = www.error + " Error Code: " + responseCode.ToString();
}
else
{
www.downloadHandler.Dispose();
}
}
var jsonContent = File.ReadAllText(jsonPath);
var appData = JsonUtility.FromJson<T>(jsonContent);
if (OnBegin != null)
{
OnBegin(appData);
}
}
public void Loop(object obj, Guid id)
{
var fields = obj.GetType().GetFields();
string val = "https://jlltest.vvhosting.co.uk/api/Floorplans" + id + "/";
foreach (FieldInfo field in fields)
{
var value = field.GetValue(obj);
//
// TODO Check "?cache=" value, if changed => download (update) the file, if not => ignore the file
//
if (value.ToString().StartsWith("!uploads"))
{
string a = value.ToString();
cachedfromJson = string.Empty;
if (!string.IsNullOrEmpty(a))
{
cachedfromJson = a.Split('?')[1];
}
if (value.ToString().Contains(".jpg"))
{
StaticCoroutine.DoCoroutine(DownloadFiles(val + value, cachedfromJson + ".jpg", "FloorPlans"));
}
if (value.ToString().Contains(".mp3"))
{
StaticCoroutine.DoCoroutine(DownloadFiles(val + value, cachedfromJson + ".mp3", "Audio"));
}
if (value.ToString().Contains(".mp4"))
{
StaticCoroutine.DoCoroutine(DownloadFiles(val + value, cachedfromJson + ".mp4", "Video"));
}
if (value.ToString().Contains(".png"))
{
StaticCoroutine.DoCoroutine(DownloadFiles(val + value, cachedfromJson + ".png", "PNGImages"));
}
if (value.ToString().Contains(".jpg"))
{
StaticCoroutine.DoCoroutine(DownloadFiles(val + value, cachedfromJson + ".jpg", "JPGImages"));
}
if (value.ToString().Contains(".pdf"))
{
StaticCoroutine.DoCoroutine(DownloadFiles(val + value, cachedfromJson + ".pdf", "PDF"));
}
}
if (field.FieldType != typeof(string))
{
Loop(value, id);
}
//
// It's collection, loop through items
//
if (typeof(IList).IsAssignableFrom(field.FieldType))
{
foreach (var v in value as IList)
{
Loop(v, id);
}
}
}
}
// Not sure how to use this to be honest
public IEnumerator CheckFileSize(string url, string filePath)
{
using (UnityWebRequest webRequest = UnityWebRequest.Head(url))
{
yield return webRequest.SendWebRequest();
if (webRequest.GetResponseHeaders() == null)
{
Debug.LogError("response header is null");
}
else
{
//webRequest.GetResponseHeader("Content-Length");
Debug.Log(webRequest.GetResponseHeader("Content-Length"));
var fileInfo = new FileInfo(filePath);
Debug.Log("The size of the file is = " + fileInfo.Length);
yield return new WaitForEndOfFrame();
if (fileInfo.Length.ToString() != webRequest.GetResponseHeader("Content-Length"))
{
Debug.Log("File isn't the same size so delete it and start download again");
File.Delete(filePath);
yield return new WaitForEndOfFrame();
needDeleting = true;
}
}
}
}
string ResponseToString(byte[] data)
{
//byte data to UTF8 encoding string
return System.Text.Encoding.UTF8.GetString(data);
}
// Method that downloads a file
public IEnumerator DownloadFiles(string url, string file, string folderStructure = "")
{
using (UnityWebRequest www = new UnityWebRequest(url))
{
byte[] buffer = new byte[256 * 1024];
www.SetRequestHeader("Cache-Control", "max-age=0, no-cache, no-store");
www.SetRequestHeader("Pragma", "no-cache");
www.chunkedTransfer = false;
string path;
if (folderStructure == "")
{
path = Path.Combine(DeviceDatabasePath, file);
}
else
{
path = Path.Combine(DeviceDatabasePath + folderStructure, file);
}
if (!Directory.Exists(Path.GetDirectoryName(path)))
{
Directory.CreateDirectory(Path.GetDirectoryName(path));
}
// Download file if it does not exist
if (!File.Exists(path))
{
yield return FireWebRequest(buffer, path, url, www);
}
else
{
yield return CheckFileSize(url, path);
if (needDeleting == true)
{
yield return FireWebRequest(buffer, path, url, www);
needDeleting = false;
}
}
}
}
private IEnumerator FireWebRequest(byte[] buffer, string path, string url, UnityWebRequest www)
{
www.downloadHandler = new FileDownloadHandler(buffer, path);
requests.Add(www);
www.timeout = 1000;
www.SendWebRequest();
Debug.Log("You are now here");
yield return DownloadProgress(www);
// Check for errors
if (www.isNetworkError || www.isHttpError)
{
long responseCode = www.responseCode;
Debug.Log(string.Format("request {0} error {1}", url, www.error + " " + responseCode.ToString()));
if (www.timeout >= 1000)
{
response.text = www.error + " Error Code: " + "504";
}
else
{
response.text = www.error + " Error Code: " + responseCode.ToString();
}
requests.Remove(www);
www.Abort();
if (OnError != null)
{
OnError(responseCode);
}
}
else
{
// File have been downloaded
Debug.Log("File successfully downloaded and saved to " + path);
if (OnComplete != null)
{
OnComplete();
}
www.downloadHandler.Dispose();
requests.Remove(www);
buffer = null;
}
}
// Download progress bar and text
public IEnumerator DownloadProgress(UnityWebRequest uwr)
{
while (!uwr.isDone)
{
progress = uwr.downloadProgress;
if (Application.internetReachability == NetworkReachability.NotReachable)
{
Debug.Log("Internet connection lost " + uwr.responseCode);
response.text = "Internet connection has been lost" + " Error Code: " + "503";
}
else
{
response.text = string.Empty;
bytesText.text = string.Format("{0} MB", (uwr.downloadedBytes / 1000000)).ToString();
}
if (OnProgress != null)
{
Debug.Log("OnProgess event not null");
OnProgress(progress);
}
yield return null;
}
}
}`
Obviously it would need some refactoring to implement within your wrapper But the way this downloader works, is check if file already exist or not, if it doesn't, it downloads it, if it exist it checks for the size of the file from server and then checks file size from persistent path if it doesn't match delete the file from path and re-download it from server, the reason i had to do this is if the app would crash of closed during download, there was no way for me to resume the download when restarting the app.
The Loop method is recursive and uses reflection, we can use this if we want to dynamically download all the available files at once without having to iterate through the json structure multiple time. It find any properties that contains the file url (providing the server is setup to have a specific suffix for each file).
I need a Post() command but no body is needed by the API. The Put(), as described by the readme, is perfect. But when coding, it still requires the body as Post(), making its functionallity exactly the same.
This should allow us implement callbacks for the async operations, instead of coroutines
Maybe with Doxygen or something that could offer similar functionality
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.