- Home /
Disable Cache for WWW
In my IPhone project, XML files are loaded via the WWW class and parsed by my game, this XML files will be updated every now and then. Sometimes after making a change to one of this xml's, uploading it, checking it was uploaded and then trying to access it in the game, the WWW returns the old file it had downloaded instead of the new one. How can I force the WWW class to download the new files everytime?
Hi Quilo,
I've stumbled over the same problem. The caching occours on Android and IOS, but not in the editor.
I've no clue how to disable the caching and wanted to ask whether you have found a solution?
thanks! Peter
Yes, it's wholly astounding there is not more interest in this - it applies in every single project, every time.
Answer by DaveA · Oct 10, 2012 at 09:47 PM
Append a random number or timestamp to your url:
url = "http://myserver/myXMLscript.php?t=" + Random.value;
That will force the url to be different each time, but your script ignores the 't' parameter. So if it does cache, it caches something that never is accessed again.
Note that for plain text files,
http://yourServer.com/project/controlFile.txt
on most (all?) web servers you can indeed add an "argument" on the end
http://yourServer.com/project/controlFile.txt?p=123123123
which is harmless and (may, probably) defeat OS-level caching strategies on devices.
Here's a simple extension that does that in a simple and consistent way:
public static string URLAntiCacheRandomizer(this string url)
{
string r = "";
r += UnityEngine.Random.Range(
1000000,8000000).ToString();
r += UnityEngine.Random.Range(
1000000,8000000).ToString();
string result = url + "?p=" + r;
return result;
}
Just use like this ...
WWW w = new WWW( fullUrl.URLAntiCacheRandomizer() );
yield return w;
Works 100.0% perfectly on both iOS and Android, on high-volume apps.
Just a reminder these days 2016+ iOS pretty much demands an ssl https URL for such things, life's easier if you have your server https.
This doesn't seem to work. Different time value, but it still grabs cached file
These two comments are basically wrong: this technique sort of "has to work", as it were, because it's the basic solution to "how to get files on the internet", regardless of platform, whether it's an app, daemon or anything else. It's likely the two commentors just had unrelated errors.
@paulius-liekis: awaking an old question with a comment "doesn't work" is pretty pointless. Show us what you actually did, on which platform you actually are and what exactly doesn't work.
@DaveA - this is definitely still a problem on ios, even with the latest patch. Your workaround, although not a perfect fix, worked like a charm. It's better than hardcode pinging with a server's ip address in my opinion.
Also found this Github workaround that I think is supposed to circumvent this problem, it's WWW class wrapper, I'm just not sure how to use it - GitHub Gist WWW workaround
Anyway, let's get back on track, Here's what I did along with my sample code. First - I stored a text file that I could get to on my server www.mydomainname.com/mytextfile.txt
my text file only has one word in it - "ok" This is the response text if we do make contact with my server (i.e. we're online)
second - here's my sample code
string url = "http://www.mydomainname.com/mytextfile.txt"+"?p="+ Random.Range(1,100000000).ToString(); //url randomdizer workaround
www mysite = new www (url);
yield return mysite;
if( mysite.text.ToString().Contains("ok") == true) {
Debug.Log("We're online");
}
if (mysite.error.ToString().Contains("offline") == true){
Debug.Log("We're not online");
}
Hope it helps. Thank again Dave.
OJ
Hi True - if you like I put in a clean tidy Extension, which implements "Dave's solution". "Dave's solution" is the conceptually correct and indeed only solution to this issue; it is indeed "how you get stuff on the net". It "can't not work" regardless of caching going on at different levels in the pipeline. (Note - for example - it's actually not possible for Unity to necessarily program around the caching that goes on inside iOS.)
Actually the issue comes form the server not being clear about what files are allowed to be cached. So it's basically a misconfigured server. See this SO post for possible solutions.
Answer by DylanYates · Aug 26, 2013 at 07:51 PM
I tried making a unique URL to avoid the caching problem but that didn't work for me. Instead I had to manually delete any cookies and cache files when the app is loaded.
void Awake() {
string dir = Application.persistentDataPath;
dir = dir.Replace("/Documents", "/Library/Cookies");
if (Directory.Exists(dir)) {
string[] filePaths = Directory.GetFiles(dir);
for (int i = 0; i < filePaths.Length; i++) {
print (filePaths[i]);
print (File.GetCreationTime("/private" + filePaths[i]));
File.Delete("/private" + filePaths[i]);
}
}
dir = dir.Replace("/Library/Cookies", "/Library/Caches/com.test.YOUR_BUNDLE_IDENTIFIER/");
if (Directory.Exists(dir)) {
string[] filePaths = Directory.GetFiles(dir);
for (int i = 0; i < filePaths.Length; i++) {
if (filePaths[i].Contains("Cache.")) {
print (filePaths[i]);
print (File.GetCreationTime("/private" + filePaths[i]));
File.Delete("/private" + filePaths[i]);
}
}
}
}
While this is an outstanding piece of code,
I fear that it only clears Unity's cache concepts. Unfortunately on, say, iOS if a URL is requested, the OS itself will "helpfully" pointlessly give you the same text again, assu$$anonymous$$g the content of the URL on the internet has not changed since last time.
(Indeed, it's somewhat unclear if Unity can even "do anything about" iOS endlessly sending the same text, ie, iOS "doesn't bother" actually going to the internet for a result.)
@Fattie, DylanYates' code does work in reality, at least for the cookie deletion. I just tested it. The problem I'm running into now is that it requires the game to ter$$anonymous$$ate before the cookie actually gets destroyed and stops getting added to every header. I think it has something to do with the fact that the cookie data is still in the game's memory somewhere (in addition to being cached in the filesystem).
Beforehand I took a look at the app data filesystem in Xcode by exporting it as a container and peeking inside AppData/Library and sure enough, there was a Cookies.binarycookies file that was created when I received a header w/ a cookie in it. When I opened it in a hex editor, I was able to read my session data (oops, Apple?).
I would argue that DaveA's answer is the most correct for the specific question of the OP, but caching avoidance isn't practical for handling a lot of things, like sessions started in php. Plus, we need a way to be able to delete cookies and purge them. It's really a terrible shame that Unity doesn't implement something like this and document it. I can't believe that more devs haven't ran into this. There's no way I'm the only one out there using session management in Unity. I was stumbling around in the dark before I even thought to do what DylanYates did.
Here's how I took a look at the app filesystem.
http://www.luby.info/2015/01/14/xcode-inspect-app-filesystem.html
Also I believe it's possible to override some iOS behavior for browser caching (although it appears you have to create a plugin in Objective-C and override some functions). $$anonymous$$aybe more of a permanent fix and less of a bandaid than DaveA's answer:
https://docs.unity3d.com/$$anonymous$$anual/iosCustomWWWRequest.html
Not sure if this would address your point about iOS sending the same text. It's hard for me to believe that Apple would be dunderheaded enough to not allow devs to override this somehow.
Anyway, if anyone or @DylanYates has any ideas for how to delete cookies on the fly like this ins$$anonymous$$d of having to kill the game to purge them, please let me know. This issue is killing me and frustrating my client.
Answer by Simon Wittber · Feb 08, 2012 at 03:16 AM
Not sure why this is happening, but the WWW class doesn't let you do many normal HTTP things. UniWeb provides control for caching in HTTP.
The fact that it doesn't work with iOS/Android basic should really be noted in the Asset Store description -- I found multiple people on the forums wondering why it doesn't work for them because they have Basic. I have iOS Pro, but I'm on Android basic so this isn't an option for me.
It's possible "BestHTTP" could solve the problem .. https://www.assetstore.unity3d.com/en/#!/content/10765
Answer by ETZerg · Jul 23, 2013 at 10:10 AM
Hi all, This is my test result: On PC and on Android, results are the same: I use WWW with GET method, and there is no cache problem.
Based on my experience in developing flash projects, DaveA's solution works. I hope it helps!
can you explain in detail or copy the part of your code ?
For 2016 this is totally wrong, on both iOS and Android you get the cache problem unfortunately.
An incredible fail by Unity .. really embarrassing.
Answer by JotaRata · Nov 14, 2015 at 10:08 PM
Maybe Caching.CleanCache() in Start/Awake would work?
see Scripting API
I fear Caching
http://docs.unity3d.com/ScriptReference/Caching.html
Only relates to asset bundles, not general web calls.