示例#1
0
        /// <summary>
        /// Requests a file from a specific url and saves it to the given filePath
        /// </summary>
        /// <param name="url"></param>
        /// <param name="filePath"></param>
        /// <param name="checksum"></param>
        /// <param name="ignoreCaching"></param>
        /// <returns></returns>
        private async Task <StorageFile> requestAsync(String url, string filePath, String checksum, Boolean ignoreCaching)
        {
            StorageFile returnFile = null;

            using (await downloadLocks.ObtainLock(url).LockAsync().ConfigureAwait(false))
            {
                // fetch file from local storage or download it?
                bool fileExists = FileUtils.exists(filePath);
                bool upToDate   = await IsFileUpToDateAsync(url, checksum).ConfigureAwait(false);

                if (fileExists && upToDate)
                {
                    // retrieve current version from cache
                    returnFile = await FileUtils.ReadFromFile(filePath).ConfigureAwait(false);
                }

                else if (NetworkUtils.isOnline())
                {
                    // download media file
                    MemoryStream saveStream = await _dataClient.performRequestAsync(new Uri( url )).ConfigureAwait(false);

                    // save data to file
                    returnFile = await FileUtils.WriteToFile(saveStream, filePath).ConfigureAwait(false);

                    await FileCacheIndex.saveAsync(url, saveStream, _config, checksum).ConfigureAwait(false);
                }
                else if (FileUtils.exists(filePath))
                {
                    // TODO notify app that data might be outdated
                    // no network: use old version from cache (even if no cache index entry exists)
                    returnFile = await FileUtils.ReadFromFile(filePath);
                }
            }

            downloadLocks.ReleaseLock(url);

            if (returnFile == null)
            {
                throw new Exception("Media file " + url + " is not in cache and no internet connection is available.");
            }

            return(returnFile);
        }
示例#2
0
        private async Task <bool> IsFileUpToDateAsync(string url, string checksum)
        {
            FileCacheIndex fileCacheIndex = await FileCacheIndex.retrieveAsync(url, _config).ConfigureAwait(false);

            if (fileCacheIndex == null)
            {
                return(false);
            }

            if (checksum != null)
            {
                // check with file's checksum
                return(!fileCacheIndex.IsOutdated(checksum));
            }
            else
            {
                // check with collection's last_modified (previewPage.last_changed would be slightly more precise)
                CollectionCacheIndex collectionCacheIndex = await CollectionCacheIndex.retrieve(_config).ConfigureAwait(false);

                DateTime collectionLastModified = collectionCacheIndex == null ? default(DateTime) : collectionCacheIndex.lastModified;
                return(collectionLastModified != null && fileCacheIndex.lastUpdated != null && !(collectionLastModified.CompareTo(fileCacheIndex.lastUpdated) > 0));
            }
        }
        /// <summary>
        /// Used to load and extract an archive to the caches
        /// </summary>
        /// <param name="ionFiles"></param>
        /// <param name="ionPages"></param>
        /// <param name="url"></param>
        /// <param name="callback"></param>
        /// <returns></returns>
        public async Task loadArchiveAsync(IIonFiles ionFiles, IIonPages ionPages, string url, Action callback = null)
        {
            // Temporary used elements in the isolated storage
            StorageFile   archiveFile = null;
            StorageFolder tempFolder  = null;

            // Get temp-folder path
            string tempFolderPath = FilePaths.getTempFolderPath(_config);

            // Lock all used elements
            using (await _fileLocks.ObtainLock(url).LockAsync().ConfigureAwait(false))
                using (await _fileLocks.ObtainLock(tempFolderPath).LockAsync().ConfigureAwait(false))
                {
                    try
                    {
                        // Request archive file
                        archiveFile = await ionFiles.requestArchiveFileAsync(url);

                        // Get tempFolder for extraction
                        tempFolder = await ApplicationData.Current.LocalFolder.CreateFolderAsync(tempFolderPath, CreationCollisionOption.ReplaceExisting);

                        // Generate fileStream from archiveFile
                        using (Stream stream = (Stream)await archiveFile.OpenStreamForReadAsync())
                        {
                            // Extract file to tempFolder
                            await TarUtils.ExtractTarArchiveAsync(stream, tempFolder).ConfigureAwait(false);
                        }

                        // Get all elements listed in the index file
                        string indexFileString = await FileIO.ReadTextAsync(await tempFolder.GetFileAsync("index.json"));

                        List <ArchiveElement> elementsList = JsonConvert.DeserializeObject <List <ArchiveElement> >(indexFileString);

                        // Handle each element of the index.json
                        for (int i = 0; i < elementsList.Count; i++)
                        {
                            IonRequestInfo requestInfo = PagesURLs.analyze(elementsList[i].url, _config);

                            // Treat every element regarding its type
                            switch (requestInfo.requestType)
                            {
                            case IonRequestType.MEDIA:
                            {
                                // Get all the needed folder- and file names
                                StorageFolder mediaFolder = await ApplicationData.Current.LocalFolder.CreateFolderAsync(FilePaths.getMediaFolderPath(_config, false), CreationCollisionOption.OpenIfExists);

                                string sourcePath      = tempFolder.Path + IonConstants.BackSlash + elementsList[i].name.Replace('/', (char)IonConstants.BackSlash[0]);
                                string destinationPath = mediaFolder.Path + IonConstants.BackSlash + FilePaths.getFileName(elementsList[i].url);

                                // Delete a possible existing file
                                if (File.Exists(destinationPath))
                                {
                                    File.Delete(destinationPath);
                                }

                                // Move the file from the temp to the media folder
                                File.Move(sourcePath, destinationPath);

                                // Create index for file
                                FileCacheIndex index = new FileCacheIndex(elementsList[i].url, elementsList[i].checksum, DateTimeUtils.now());

                                // Save file index
                                await CacheIndexStore.save(elementsList[i].url, index, _config).ConfigureAwait(false);

                                break;
                            }

                            case IonRequestType.PAGE:
                            {
                                // Extract the page json from the file
                                string pageString = await FileIO.ReadTextAsync(await tempFolder.GetFileAsync(elementsList[i].name.Replace('/', (char)IonConstants.BackSlash[0])));

                                // Parse the new page
                                IonPage page = DataParser.parsePage(pageString);

                                // Save the page to the caches
                                await ionPages.savePageToCachesAsync(page, _config).ConfigureAwait(false);

                                break;
                            }

                            default:
                            {
                                IonLogging.log("Object " + elementsList[i].url + " could not be parsed from archive.", IonLogMessageTypes.ERROR);
                                break;
                            }
                            }
                        }
                    }

                    catch (Exception e)
                    {
                        IonLogging.log("Error at the archive download: " + e.Message, IonLogMessageTypes.ERROR);
                    }

                    finally
                    {
                        // Clean up all temperary used elements
                        if (archiveFile != null)
                        {
                            // Delete index file
                            string indexFilePath = FilePaths.getCacheIndicesFolderPath(_config) + IonConstants.BackSlash + archiveFile.Name + IonConstants.JsonFileExtension;

                            if (File.Exists(indexFilePath))
                            {
                                File.Delete(indexFilePath);
                            }

                            // Delete archive file
                            await archiveFile.DeleteAsync();
                        }

                        if (tempFolder != null)
                        {
                            await tempFolder.DeleteAsync();
                        }

                        // Call the callback action if set before
                        if (callback != null)
                        {
                            callback();
                        }
                    }
                }

            // Release the file locks
            _fileLocks.ReleaseLock(url);
            _fileLocks.ReleaseLock(tempFolderPath);
        }