/// <summary> /// 处理下载文件块 /// </summary> /// <param name="message">消息</param> /// <param name="fileName">下载文件名</param> /// <param name="chunkNumber">块号</param> /// <returns>文件块信息</returns> async Task <FileChunkInfo> IFileGrain.DownloadFileChunk(string message, string fileName, int chunkNumber) { if (chunkNumber <= 0) { return(null); } string sourcePath = Path.Combine(DownloadPath, fileName); if (!File.Exists(sourcePath)) { throw new InvalidOperationException(String.Format("不存在下载文件: {0}", fileName)); } await using (FileStream sourceStream = new FileStream(sourcePath, FileMode.Open, FileAccess.Read, FileShare.Read)) { FileChunkInfo result = await FileChunkInfo.CreateAsync(sourceStream, fileName, chunkNumber, MaxChunkSize); if (result.Done && _service != null) { await _service.AfterDownloadFile(message, sourcePath); } return(result); } }
/// <summary> /// 上传文件 /// </summary> /// <param name="message">上传消息</param> /// <param name="fileName">上传文件名</param> /// <param name="sourceStream">读取文件流</param> /// <param name="doProgress">执行进度的回调函数, 回调函数返回值如为false则中止上传</param> /// <returns>完成上传时返回消息</returns> public async Task <string> UploadFileAsync(string message, string fileName, Stream sourceStream, Func <FileChunkInfo, bool> doProgress) { if (sourceStream == null) { throw new ArgumentNullException(nameof(sourceStream)); } string result = null; const int maxChunkSize = 64 * 1024; int chunkCount = (int)Math.Ceiling(sourceStream.Length * 1.0 / maxChunkSize); for (int i = 1; i <= chunkCount; i++) { int chunkSize = i < chunkCount ? maxChunkSize : (int)(sourceStream.Length - maxChunkSize * (chunkCount - 1)); byte[] chunkBody = new byte[chunkSize]; sourceStream.Seek(maxChunkSize * (i - 1), SeekOrigin.Begin); await sourceStream.ReadAsync(chunkBody, 0, chunkSize); FileChunkInfo chunkInfo = new FileChunkInfo(fileName, chunkCount, i, chunkSize, maxChunkSize, chunkBody); if (doProgress == null || doProgress(chunkInfo)) { result = await UploadFileChunkAsync(message, chunkInfo); } else { return(await UploadFileChunkAsync(message, new FileChunkInfo(fileName))); } } return(result); }
/// <summary> /// 下载文件 /// </summary> /// <param name="message">上传消息</param> /// <param name="fileName">下载文件名</param> /// <param name="targetStream">写入文件流</param> /// <param name="doProgress">执行进度的回调函数, 回调函数返回值如为false则中止下载</param> public async Task DownloadFileAsync(string message, string fileName, Stream targetStream, Func <FileChunkInfo, bool> doProgress) { if (targetStream == null) { throw new ArgumentNullException(nameof(targetStream)); } for (int i = 1; i < Int32.MaxValue; i++) { FileChunkInfo chunkInfo = await DownloadFileChunkAsync(message, fileName, i); if (doProgress != null && !doProgress(chunkInfo)) { break; } if (chunkInfo == null) { break; } targetStream.Seek(chunkInfo.MaxChunkSize * (chunkInfo.ChunkNumber - 1), SeekOrigin.Begin); await targetStream.WriteAsync(chunkInfo.ChunkBody); await targetStream.FlushAsync(); if (chunkInfo.Over) { break; } } }
/// <summary> /// 上传文件 /// </summary> /// <param name="message">上传消息</param> /// <param name="chunkInfo">上传文件块信息</param> /// <returns>完成上传时返回消息</returns> public async Task <string> UploadFileChunkAsync(string message, FileChunkInfo chunkInfo) { if (chunkInfo == null) { throw new ArgumentNullException(nameof(chunkInfo)); } using (MultipartFormDataContent formDataContent = new MultipartFormDataContent()) { formDataContent.Add(new StringContent(message, Encoding.UTF8), "message"); formDataContent.Add(new StringContent(Utilities.JsonSerialize(chunkInfo), Encoding.UTF8), "chunkInfo"); return(await CallAsync <string>(HttpMethod.Put, ApiConfig.ApiInoutFilePath, formDataContent)); } }
public FileSplitInfo GetFileSplitInfo() { var chunkLengths = GetChunkLengths(); var splitInfo = new FileSplitInfo(chunkLengths.Length); for (long id = 0, position = 0; id < splitInfo.ChunkCount; id++) { var fileChunkInfo = new FileChunkInfo(id, chunkLengths[id]) { Position = position }; splitInfo.Chunks[id] = fileChunkInfo; position += fileChunkInfo.Length; } return splitInfo; }
/// <summary> /// 处理上传文件块 /// </summary> /// <param name="message">消息</param> /// <param name="chunkInfo">文件块信息</param> /// <returns>完成上传时返回消息</returns> async Task <string> IFileGrain.UploadFileChunk(string message, FileChunkInfo chunkInfo) { string targetPath = Path.Combine(UploadPath, chunkInfo.FileName); if (chunkInfo.Stop) { if (File.Exists(targetPath)) { File.Delete(targetPath); } } else { try { await using (FileStream targetStream = new FileStream(targetPath, FileMode.OpenOrCreate, FileAccess.Write)) { await chunkInfo.WriteAsync(targetStream); } } catch (OperationCanceledException) { if (File.Exists(targetPath)) { File.Delete(targetPath); } throw; } if (chunkInfo.Done && _service != null) { return(await _service.AfterUploadFile(message, targetPath)); } } return(null); }