I use a file stream to do exactly what you are trying to implement. The benefits to this is that it is easy to implement pause functionality, implement progress meters and run other computations whilst the data is being streamed in.
I wish that I could take responsibility for all of the code below, however some of it is a modified version of code found here: http://answers.unity3d.com/questions/300841/ios-download-files-and-store-to-local-drive.html
Includes:
using UnityEngine;
using UnityEngine.UI;
using System;
using System.Collections;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
Connect to server:
Check to see whether we actually can get the files that we want. If we can, then initiate loading.
Start()
{
try
{
using (WebClient client = new WebClient())
{
using (Stream stream = client.OpenRead("http://myserver.com"))
{
Debug.Log("Connected to server");
InitiateLoad();
}
}
}
catch
{
Debug.Log("Failed to connect to server");
}
}
Check for the file in persistent data: I have implemented 2 steps during this phase. Firstly, we want to load the video if the file does not exist in persistent data and secondly, if the file does exist, but does not match the file size on the server, then re-download the file. The reason for this is that if say the user quits the application mid download, then the file will exist in persistent data, however will not be complete.
private void InitiateLoad()
{
if (!Directory.Exists(Application.persistentDataPath + "/" + folderPath))
{
Debug.Log("Domain Does Not Exsist");
Directory.CreateDirectory(Application.persistentDataPath + "/" + folderPath);
}
if(!File.Exists(URI))
{
SetupLoader();
}
else
{
long existingFileSize = new FileInfo(path).Length;
long expectedFileSize = 0;
string url = "http://myserver.com/" + folderPath + URI;
System.Net.WebRequest req = System.Net.HttpWebRequest.Create(url);
req.Method = "HEAD";
using (System.Net.WebResponse resp = req.GetResponse())
{
int ContentLength;
if(int.TryParse(resp.Headers.Get("Content-Length"), out ContentLength))
{
expectedFileSize = ContentLength;
}
}
if(existingFileSize != expectedFileSize)
{
SetupLoader();
}
}
}
Start Loading: If we need to load the content then this function is called.
private void SetupLoader()
{
string query = "GET " + "/" + folderPath + URIToLoad.Replace(" ", "%20") + " HTTP/1.1\r\n" +
"Host: "http://myserver.com"\r\n" +
"User-Agent: undefined\r\n" +
"Connection: close\r\n" +
"\r\n";
if (!Directory.Exists(Application.persistentDataPath + "/" + folderPath))
{
Directory.CreateDirectory(Application.persistentDataPath + "/" + folderPath);
}
client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
client.Connect(http://myserver.com", 80);
networkStream = new NetworkStream(client);
var bytes = Encoding.Default.GetBytes(query);
networkStream.Write(bytes, 0, bytes.Length);
var bReader = new BinaryReader(networkStream, Encoding.Default);
string response = "";
string line;
char c;
do
{
line = "";
c = '\u0000';
while (true)
{
c = bReader.ReadChar();
if (c == '\r')
break;
line += c;
}
c = bReader.ReadChar();
response += line + "\r\n";
}
while (line.Length > 0);
Regex reContentLength = new Regex(@"(?<=Content-Length:\s)\d+", RegexOptions.IgnoreCase);
// Get the total number of bytes of the file we are downloading
contentLength = uint.Parse(reContentLength.Match(response).Value);
fileStream = new FileStream(Application.persistentDataPath + "/" + folderPath + URIToLoad, FileMode.Create);
totalDownloaded = 0;
contentDownloading = true;
}
Download: Start downloading! Note that if you want to pause, simply change the contentDownloading bool.
private void Update()
{
if (contentDownloading)
{
byte[] buffer = new byte[1024 * 1024];
if (totalDownloaded < contentLength)
{
if (networkStream.DataAvailable)
{
read = (uint)networkStream.Read(buffer, 0, buffer.Length);
totalDownloaded += read;
fileStream.Write(buffer, 0, (int)read);
}
int percent = (int)((totalDownloaded/(float)contentLength) * 100);
Debug.Log("Downloaded: " + totalDownloaded + " of " + contentLength + " bytes ..." + percent);
}
else
{
fileStream.Flush();
fileStream.Close();
client.Close();
Debug.Log("Load Complete");
LoadNextContent();
}
}
}
Hope this helps :)