/// <summary> /// 开始上传 /// </summary> /// <param name="upload"></param> public async void UploadStart(Upload upload) { UploadStatus = UploadStatus.Uploading; if (upload != null && upload.FileType != (int)FileType.UNKNOWN) { using (FileStream fileStream = new FileStream(upload.FilePath, FileMode.Open, FileAccess.Read)) { var buffer = new byte[CHUNKSIZE]; int chunkNumber = upload.ChunkNumber; int totalSize = upload.FileSize; int totalChunks = (int)Math.Ceiling((double)totalSize / CHUNKSIZE); int bytesRead = 0; int offset = chunkNumber * CHUNKSIZE; int uploadedLength = offset; fileStream.Seek((long)offset, SeekOrigin.Begin); while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0) { //如果暂停了 if (UploadStatus == UploadStatus.Pause) { break; } //开始时间 var watch = new Stopwatch(); watch.Start(); //byte转换 var finalBuffer = new byte[bytesRead]; Buffer.BlockCopy(buffer, 0, finalBuffer, 0, bytesRead); //上传一个分片 var response = await HttpManager.Instance.BreakPointUploadAsync <BreakPointUploadResponse>( new UploadAlbumFileRequest(upload.TargetId, upload.AlbumId, (AlbumType)upload.AlbumType, upload.FileName, (FileType)upload.FileType, upload.Identifier, totalSize, totalChunks, chunkNumber, CHUNKSIZE, bytesRead), finalBuffer ); Logger.Log(response.message); //当前分片上传失败(只要不是完成和分片成功都视为失败) if (!response.Ok && response.code != 201) { OnUploadFailure?.Invoke(); break; } //上传完成 if (response.Ok) { OnUploadCompleted?.Invoke(); UploadManager.DeleteUploader(upload); break; } var progress = Convert.ToDouble((uploadedLength / (Double)totalSize) * 100); //当前分片上传成功 upload.Progress = progress; upload.ChunkNumber = chunkNumber; var a = UploadManager.UpdateUploader(upload); chunkNumber++;//文件块序号+1 //结束时间 watch.Stop(); uploadedLength += bytesRead; //速度计算byte/s var speed = CHUNKSIZE * 1000L / watch.ElapsedMilliseconds; //计算剩余时间 var time = (totalSize - uploadedLength) / speed; //上传进度通知 OnUploadProgressChanged?.Invoke(progress, (int)time, speed / 1024); } } } }
/// <summary> /// Uploads a file to a given path. /// </summary> /// <param name="fileContents">The file contents.</param> /// <param name="fileName">The file name (including extension).</param> /// <param name="fileType">The file content type.</param> /// <param name="path">The path to upload the file to.</param> /// <returns>Either the uploaded file or an error.</returns> public Task <Option <CloudFile, Error> > UploadFile(System.IO.Stream fileContents, string fileName, string mimeType, string path) => // TODO: Decide whether to create a new folder if the provided doesn't exist GetFolderIdFromPathAsync(path).MapAsync(async parentFolderId => { var fileMetadata = new File() { Name = fileName, Parents = new[] { parentFolderId }, MimeType = mimeType }; var uploadRequest = _driveService .Files .Create(fileMetadata, fileContents, fileMetadata.MimeType); // Return the id and name fields when finished uploading uploadRequest.Fields = "id,name"; uploadRequest.ChunkSize = ResumableUpload.MinimumChunkSize; uploadRequest.ProgressChanged += progress => { switch (progress.Status) { case UploadStatus.NotStarted: break; case UploadStatus.Starting: OnUploadStarting?.Invoke(new UploadStarting { FileName = fileName, DestinationPath = path, FileSizeInBytes = fileContents.Length }); break; case UploadStatus.Uploading: OnUploadProgressChanged?.Invoke(new UploadProgress { FileName = fileName, BytesSent = progress.BytesSent, TotalBytesToSend = fileContents.Length }); break; case UploadStatus.Completed: OnUploadSuccessfull?.Invoke(new UploadSuccessResult { FileName = fileName, Path = path }); break; case UploadStatus.Failed: OnUploadFailure?.Invoke(new UploadFailureResult { FileName = fileName, Path = path, Exception = progress.Exception }); break; default: break; } }; var result = await uploadRequest.UploadAsync(); var uploadedFile = uploadRequest.ResponseBody; return(uploadedFile); }) .MapAsync(async f => ToCloudFile(f));