/// <summary> /// Checks whether a file exists and is fresh. /// </summary> /// <param name="path">the path to the cached file</param> /// <param name="cacheStrategy">decides cache state and duration</param> /// <returns></returns> public static CacheResult IsFileCached(string path, ICacheStrategy cacheStrategy) { try { FileInfo info = new FileInfo(path); DateTime cachedUntil; if (info.Exists) { cachedUntil = cacheStrategy.GetCachedUntil(path); if (DateTime.Now < cachedUntil) return new CacheResult(path, false, CacheState.Cached, cachedUntil); else return new CacheResult(path, false, CacheState.CachedOutOfDate, cachedUntil); } else { return CacheResult.Uncached(path); } } catch (Exception ex) { return CacheResult.Uncached(path, ex); } }
/// <summary> /// Caches a file from the internets. /// </summary> /// <param name="method">specifies GET or POST</param> /// <param name="url">the url to request</param> /// <param name="cachePath">the path where the cached file will be saved</param> /// <param name="cacheStrategy">decides file cache state and duration</param> /// <param name="parameters">parameters for POST requests</param> /// <param name="action">a validation or processing action to be run after downloading the file but before copying it to <paramref name="cachePath"/></param> private static CacheResult CacheFileInternal(HttpMethod method, string url, string cachePath, ICacheStrategy cacheStrategy, IEnumerable<KeyValuePair<string, string>> parameters, PostDownloadAction action) { CacheResult currentResult; string tempPath = null; // validate parameters if (method == HttpMethod.Get && parameters != null) throw new ArgumentException("GET method and parameters don't mix"); // check whether the file is cached currentResult = IsFileCached(cachePath, cacheStrategy); if (currentResult.State == CacheState.Cached) return currentResult; try { // download to a temp file switch (method) { case HttpMethod.Get: tempPath = DownloadUrlGet(url); break; case HttpMethod.Post: tempPath = DownloadUrlPost(url, parameters); break; default: throw new ArgumentException("Unknown HTTP method " + method.ToString()); } // call the PostDownloadAction if there is one if (action != null) action(tempPath); // we assume the file is fine if the PostDownloadAction didn't throw an exception File.Copy(tempPath, cachePath, true); // return success return new CacheResult(cachePath, true, CacheState.Cached, cacheStrategy.GetCachedUntil(cachePath)); } catch (Exception ex) { // if we currently have a valid local copy of the file, even if out of date, return that info if (currentResult.State != CacheState.Uncached) return CacheResult.FromExisting(currentResult, ex); else return CacheResult.Uncached(ex); } finally { // get rid of the temp file, don't care if it doesn't work try { if (!string.IsNullOrEmpty(tempPath)) File.Delete(tempPath); } catch { /* pass */ } } }