- Home /
iOS download files and store to local drive
Hey guys, i currently have a working code for downloading files from the web in iOS, i am given a URL, and i use WWW to download the file. after the download is complete (the isDone of www is true), I save the file using C#'s System.IO.
my problem is i need to use a download method (or workaround) that allows me to securely download files. What would happen if the device sleeps during WWW? will the download resume when the device comes out of sleep or will the download fail?
I need a method to also show my progress in downloading the files. I have read that the WWW.progress method does not work for UNITY iOS.
The files i am currently downloading are 6 mb each, but it will increase up to 50mb to 100mb files, so I need a better alternative to WWW.
I am wondering if there is a native plugin/ code to be able to make iOS handle the download instead of using the Unity engine's WWW class to handle it. or How i would be able to workaround this problem.
thanks!
This solution is not working for me. Can anyone share what references to use on top of the code. Obviously the using System.IO; using System.Net.Sockets; need to be used. However what extra references need to be used? Thanks for your help!
Here is a very good plugin to download big files from web and save locally.
https://assetstore.unity.com/packages/tools/network/large-file-downloader-cross-platform-92128
Answer by franky303 · Sep 26, 2012 at 08:29 AM
// Based on this:
// http://stackoverflow.com/questions/4768443/downloading-file-via-tcpclient-from-http-server
public class main : MonoBehaviour
{
string host = "www.server.com";
string uri = "/path/to/file/1920x1080.mp4";
uint contentLength;
int n = 0;
int read = 0;
NetworkStream networkStream;
FileStream fileStream;
Socket client;
// Use this for initialization
void Start ()
{
string query = "GET " + uri.Replace(" ", "%20") + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"User-Agent: undefined\r\n" +
"Connection: close\r\n"+
"\r\n";
Debug.Log (query);
client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
client.Connect(host, 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);
Debug.Log ( response );
Regex reContentLength = new Regex(@"(?<=Content-Length:\s)\d+", RegexOptions.IgnoreCase);
contentLength = uint.Parse(reContentLength.Match(response).Value);
fileStream = new FileStream( Application.persistentDataPath + "/download.mp4", FileMode.Create);
}
void Update()
{
byte[] buffer = new byte[256 * 1024];
if (n < contentLength)
{
if (networkStream.DataAvailable)
{
read = networkStream.Read(buffer, 0, buffer.Length);
n += read;
fileStream.Write(buffer, 0, read);
}
Debug.Log ( "Downloaded: " + n + " of " + contentLength + " bytes ..." );
}
else
{
fileStream.Flush();
fileStream.Close();
client.Close();
}
}
}
Works like a charm and also fixes one issue I was having while downloading large files on iOS, which was causing crashes due to excessive memory usage.
One thing that is not so great though, is that the download time is much larger than using regular WWW.
Hello André, you are absolutely right. the version i initially posted only used a 4 kilobyte download buffer and therefore it was slow. simply increase the byte[] buffer = new byte[4 1024]; to e.g. byte[] buffer = new byte[256 1024]; and it will be a lot faster! i have edited the code above already, so people can simply copy/paste it.
Thanks ;) I had figured as much. Now the download speed is much greater.
This is the solution I'm currently using, but I'm getting socket connection exceptions when the internet connection is set up to use a proxy server. Do you have a solution for this case?
Using this script (which is great btw)... what happens if the datastream is interrupted?
During the statement if (n < contentLength) there doesn't appear to be a check to see if the the stream stops before contentLength is met.
Or am I wrong to think this.. because the datastream has already been read and therefore contentLength cannot be wrong?
I'm asking because I think I have run into a couple instances of an endless loop here.
Answer by franky303 · Sep 25, 2012 at 08:42 AM
Hello, i have also had issues with WWW.progress initially, however it DOES work. Check out this example, it is working for me on unity 3.5.5 (pro). The mistake i made was checking WWW.progress inside Start(), but when i poll it in Update() it gives correct values. I have also read somewhere on the forum, there might have been a bug which requires you to poll WWW.isDone in order to update the WWW.progress value. However in my test with unity 3.5.5 this wasn't necessary:
#pragma strict
var url = "http://www.blabla.com/somebigfile.mp4";
var downloader: WWW = null;
function Start ()
{
downloader = new WWW (url);
yield downloader;
}
function Update ()
{
if ( downloader != null )
{
// value between 0 and 1
print( "Download Progress: " + 100*downloader.progress + "% ..." );
}
}
Answer by Ing3nu · Apr 07, 2015 at 03:57 PM
Hi franky303! What references are you using at the very top of the script? I think I'm missing one because "NetworkStream" is throwing errors. Thanks!
These are my imports:
using UnityEngine;
using System.Collections;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;
using System;
Answer by DeveshPandey · Mar 31, 2018 at 08:40 PM
Here is a nice plugin, its very easy to use. You can download any small or big file from the web. Must see this plugin
https://www.assetstore.unity3d.com/#!/content/92128?aid=1101l34jr
For more details visit this blog