/// <summary> /// 下载图片,不在本地缓存文件,直接返回BitmapImage对象 /// </summary> /// <param name="p_path">要下载的文件路径</param> /// <returns></returns> public static async Task <BitmapImage> GetImage(string p_path) { if (string.IsNullOrEmpty(p_path)) { return(null); } // 路径肯定含/ int index = p_path.LastIndexOf('/'); if (index <= 0) { return(null); } MemoryStream stream = new MemoryStream(); DownloadInfo info = new DownloadInfo { Path = p_path, TgtStream = stream, }; bool suc = false; try { suc = await GetFile(info, CancellationToken.None); if (suc) { stream.Seek(0, SeekOrigin.Begin); BitmapImage bmp = new BitmapImage(); #if UWP var randomStream = new InMemoryRandomAccessStream(); var outputStream = randomStream.GetOutputStreamAt(0); await RandomAccessStream.CopyAsync(stream.AsInputStream(), outputStream); await bmp.SetSourceAsync(randomStream); #else await bmp.SetSourceAsync(stream); #endif return(bmp); } } finally { stream.Close(); } return(null); }
/// <summary> /// 下载文件并缓存到本地 /// </summary> /// <param name="p_path">要下载的文件路径,以原有文件名缓存到本地</param> /// <returns>false 下载失败,缓存文件已删除</returns> public static async Task <bool> GetAndCacheFile(string p_path) { if (string.IsNullOrEmpty(p_path)) { return(false); } // 路径肯定含/ int index = p_path.LastIndexOf('/'); if (index <= 0) { return(false); } string path = Path.Combine(Kit.CachePath, p_path.Substring(index + 1)); FileStream stream = File.Create(path); DownloadInfo info = new DownloadInfo { Path = p_path, TgtStream = stream, }; bool suc = false; try { suc = await GetFile(info, CancellationToken.None); } finally { stream.Close(); } if (!suc) { // 未成功,删除缓存文件,避免打开时出错 try { // mono中 FileInfo 的 Exists 状态不同步! if (System.IO.File.Exists(path)) { System.IO.File.Delete(path); } } catch { } } return(suc); }
/// <summary> /// 执行下载 /// </summary> /// <param name="p_priorThumbnail">是否优先下载缩略图</param> /// <param name="p_prompt">是否提示下载失败信息</param> /// <returns></returns> internal async Task <bool> Download(bool p_priorThumbnail = false, bool p_prompt = true) { if (State != FileItemState.None || string.IsNullOrEmpty(ID)) { if (p_prompt) { Kit.Warn("当前状态不可下载!"); } return(false); } bool downloadThumb = false; if (p_priorThumbnail) { // 优先下载缩略图时,先判断是否存在 downloadThumb = await AtFile.Exists(ID + ThumbPostfix); // 缩略图不存在时,若为视频文件不下载 if (!downloadThumb && FileType != FileItemType.Image) { return(false); } } string path = Path.Combine(Kit.CachePath, downloadThumb ? GetThumbName() : GetFileName()); FileStream stream = null; try { if (System.IO.File.Exists(path)) { System.IO.File.Delete(path); } stream = System.IO.File.Create(path); } catch (Exception ex) { if (p_prompt) { Kit.Warn("创建文件出错!"); } Log.Error(ex, "下载前创建文件出错!"); return(false); } State = FileItemState.Downloading; DownloadInfo info = new DownloadInfo { Path = downloadThumb ? ID + ThumbPostfix : ID, TgtStream = stream, Progress = OnDownloadProgress, }; bool suc = false; _ctsDownload?.Dispose(); _ctsDownload = new CancellationTokenSource(); try { suc = await Downloader.GetFile(info, _ctsDownload.Token); } catch (Exception ex) { Log.Error(ex, "下载出错"); } finally { _ctsDownload?.Dispose(); info.TgtStream.Close(); State = FileItemState.None; } if (!suc) { if (p_prompt) { Kit.Warn(info.Error); } // 未成功,删除缓存文件,避免打开时出错 try { // mono中 FileInfo 的 Exists 状态不同步! if (System.IO.File.Exists(path)) { System.IO.File.Delete(path); } } catch { } } else { VisualStateManager.GoToState(this, "Cached", true); } return(suc); }
/// <summary> /// 下载文件,将下载内容写入目标流 /// </summary> /// <param name="p_info">下载描述</param> /// <param name="p_token"></param> /// <returns>是否成功</returns> public static async Task <bool> GetFile(DownloadInfo p_info, CancellationToken p_token) { if (p_info == null || string.IsNullOrEmpty(p_info.Path) || p_info.TgtStream == null) { return(false); } HttpResponseMessage response = null; using (await _locker.LockAsync()) using (var request = CreateRequestMessage(p_info.Path)) { try { response = await _client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, p_token).ConfigureAwait(false); } catch (TaskCanceledException) { p_info.Error = "已取消下载!"; return(false); } catch (Exception ex) { p_info.Error = "😢下载过程中出错!" + ex.Message; return(false); } } // 下载失败 if (response.Headers.TryGetValues("error", out var vals)) { p_info.Error = WebUtility.UrlDecode(vals.First()); return(false); } // 文件长度 long total; if (!response.Content.Headers.TryGetValues("Content-Length", out var lgh) || !long.TryParse(lgh.First(), out total)) { p_info.Error = "😢待下载的文件长度未知,下载失败!"; return(false); } try { using (var inputStream = await response.Content.ReadAsStreamAsync()) { int read; int readTotal = 0; byte[] data = new byte[81920]; while ((read = await inputStream.ReadAsync(data, 0, data.Length, p_token).ConfigureAwait(false)) > 0) { await p_info.TgtStream.WriteAsync(data, 0, read); readTotal += read; p_info.Progress?.Invoke(read, readTotal, total); } await p_info.TgtStream.FlushAsync(); } } catch (TaskCanceledException) { p_info.Error = "已取消下载!"; return(false); } catch (Exception ex) { p_info.Error = "😢下载过程中出错!" + ex.Message; return(false); } return(true); }