private void makeBlock(string upHost, long offset, int blockSize, int chunkSize, ProgressHandler progressHandler, CompletionHandler completionHandler) { string url = string.Format("{0}/mkblk/{1}", upHost, blockSize); try { this.fileStream.Read(this.chunkBuffer, 0, chunkSize); } catch (Exception ex) { this.upCompletionHandler(this.key, ResponseInfo.fileError(ex), ""); return; } this.crc32 = CRC32.CheckSumSlice(this.chunkBuffer, 0, chunkSize); this.mHttpManager.postData(url, this.upHeaders, this.chunkBuffer, 0, chunkSize, HttpManager.FORM_MIME_OCTECT, new CompletionHandler(delegate(ResponseInfo respInfo, string response) { progressHandler(offset, this.size); completionHandler(respInfo, response); })); }
private void putChunk(string upHost, long offset, int chunkSize, string context, ProgressHandler progressHandler, CompletionHandler completionHandler) { int chunkOffset = (int)(offset % Config.BLOCK_SIZE); string url = string.Format("{0}/bput/{1}/{2}", upHost, context, chunkOffset); try { this.fileStream.Read(this.chunkBuffer, 0, chunkSize); } catch (Exception ex) { this.upCompletionHandler(this.key, ResponseInfo.fileError(ex), ""); return; } this.crc32 = CRC32.CheckSumSlice(this.chunkBuffer, 0, chunkSize); this.mHttpManager.postData(url, this.upHeaders, this.chunkBuffer, 0, chunkSize, HttpManager.FORM_MIME_OCTECT, new CompletionHandler(delegate(ResponseInfo respInfo, string response) { progressHandler(offset, this.size); completionHandler(respInfo, response); })); }
/// <summary> /// 上传数据片,同时检查CRC32 /// </summary> /// <param name="chunkBuffer">数据片</param> /// <param name="offset">当前片在块中的偏移位置</param> /// <param name="chunkSize">当前片的大小</param> /// <param name="context">承接前一片数据用到的Context</param> /// <param name="upToken">上传凭证</param> /// <returns>此操作执行后的返回结果</returns> private HttpResult BputChunk(byte[] chunkBuffer, long offset, long chunkSize, string context, string upToken) { HttpResult result = new HttpResult(); try { //get upload host string ak = UpToken.GetAccessKeyFromUpToken(upToken); string bucket = UpToken.GetBucketFromUpToken(upToken); if (ak == null || bucket == null) { return(HttpResult.InvalidToken); } string uploadHost = this.config.UpHost(ak, bucket); string url = string.Format("{0}/bput/{1}/{2}", uploadHost, context, offset); string upTokenStr = string.Format("UpToken {0}", upToken); using (MemoryStream ms = new MemoryStream(chunkBuffer, 0, (int)chunkSize)) { byte[] data = ms.ToArray(); result = httpManager.PostData(url, data, upTokenStr); if (result.Code == (int)HttpCode.OK) { Dictionary <string, string> rd = JsonConvert.DeserializeObject <Dictionary <string, string> >(result.Text); if (rd.ContainsKey("crc32")) { uint crc_1 = Convert.ToUInt32(rd["crc32"]); uint crc_2 = CRC32.CheckSumSlice(chunkBuffer, 0, (int)chunkSize); if (crc_1 != crc_2) { result.RefCode = (int)HttpCode.USER_NEED_RETRY; result.RefText += string.Format(" CRC32: remote={0}, local={1}\n", crc_1, crc_2); } } else { result.RefText += string.Format("[{0}] JSON Decode Error: text = {1}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.ffff"), result.Text); result.RefCode = (int)HttpCode.USER_NEED_RETRY; } } else { result.RefCode = (int)HttpCode.USER_NEED_RETRY; } } } catch (Exception ex) { StringBuilder sb = new StringBuilder(); sb.AppendFormat("[{0}] bput Error: ", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.ffff")); Exception e = ex; while (e != null) { sb.Append(e.Message + " "); e = e.InnerException; } sb.AppendLine(); if (ex is QiniuException) { QiniuException qex = (QiniuException)ex; result.Code = qex.HttpResult.Code; result.RefCode = qex.HttpResult.Code; result.Text = qex.HttpResult.Text; result.RefText += sb.ToString(); } else { result.RefCode = (int)HttpCode.USER_UNDEF; result.RefText += sb.ToString(); } } return(result); }
/// <summary> /// 创建块(携带首片数据),同时检查CRC32 /// </summary> /// <param name="resumeBlockerObj">创建分片上次的块请求</param> private void MakeBlock(object resumeBlockerObj) { ResumeBlocker resumeBlocker = (ResumeBlocker)resumeBlockerObj; ManualResetEvent doneEvent = resumeBlocker.DoneEvent; Dictionary <long, HttpResult> blockMakeResults = resumeBlocker.BlockMakeResults; PutExtra putExtra = resumeBlocker.PutExtra; long blockIndex = resumeBlocker.BlockIndex; HttpResult result = new HttpResult(); //check whether to cancel while (true) { UploadControllerAction upCtl = resumeBlocker.PutExtra.UploadController(); if (upCtl == UploadControllerAction.Suspended) { doneEvent.WaitOne(1000); continue; } else if (upCtl == UploadControllerAction.Aborted) { doneEvent.Set(); result.Code = (int)HttpCode.USER_CANCELED; result.RefCode = (int)HttpCode.USER_CANCELED; result.RefText += string.Format("[{0}] [ResumableUpload] Info: upload task is aborted, mkblk {1}\n", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.ffff"), blockIndex); blockMakeResults.Add(blockIndex, result); return; } else { break; } } byte[] blockBuffer = resumeBlocker.BlockBuffer; int blockSize = blockBuffer.Length; string upToken = resumeBlocker.UploadToken; Dictionary <string, long> uploadedBytesDict = resumeBlocker.UploadedBytesDict; long fileSize = resumeBlocker.FileSize; object progressLock = resumeBlocker.ProgressLock; ResumeInfo resumeInfo = resumeBlocker.ResumeInfo; try { //get upload host string ak = UpToken.GetAccessKeyFromUpToken(upToken); string bucket = UpToken.GetBucketFromUpToken(upToken); if (ak == null || bucket == null) { result = HttpResult.InvalidToken; doneEvent.Set(); return; } string uploadHost = this.config.UpHost(ak, bucket); string url = string.Format("{0}/mkblk/{1}", uploadHost, blockSize); string upTokenStr = string.Format("UpToken {0}", upToken); using (MemoryStream ms = new MemoryStream(blockBuffer, 0, blockSize)) { byte[] data = ms.ToArray(); result = httpManager.PostData(url, data, upTokenStr); if (result.Code == (int)HttpCode.OK) { ResumeContext rc = JsonConvert.DeserializeObject <ResumeContext>(result.Text); if (rc.Crc32 > 0) { uint crc_1 = rc.Crc32; uint crc_2 = CRC32.CheckSumSlice(blockBuffer, 0, blockSize); if (crc_1 != crc_2) { result.RefCode = (int)HttpCode.USER_NEED_RETRY; result.RefText += string.Format(" CRC32: remote={0}, local={1}\n", crc_1, crc_2); } else { //write the mkblk context resumeInfo.Contexts[blockIndex] = rc.Ctx; resumeInfo.ExpiredAt = rc.ExpiredAt; lock (progressLock) { uploadedBytesDict["UploadProgress"] += blockSize; } putExtra.ProgressHandler(uploadedBytesDict["UploadProgress"], fileSize); } } else { result.RefText += string.Format("[{0}] JSON Decode Error: text = {1}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.ffff"), result.Text); result.RefCode = (int)HttpCode.USER_NEED_RETRY; } } else { result.RefCode = (int)HttpCode.USER_NEED_RETRY; } } } catch (Exception ex) { StringBuilder sb = new StringBuilder(); sb.AppendFormat("[{0}] mkblk Error: ", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.ffff")); Exception e = ex; while (e != null) { sb.Append(e.Message + " "); e = e.InnerException; } sb.AppendLine(); if (ex is QiniuException) { QiniuException qex = (QiniuException)ex; result.Code = qex.HttpResult.Code; result.RefCode = qex.HttpResult.Code; result.Text = qex.HttpResult.Text; result.RefText += sb.ToString(); } else { result.RefCode = (int)HttpCode.USER_UNDEF; result.RefText += sb.ToString(); } } //return the http result blockMakeResults.Add(blockIndex, result); doneEvent.Set(); }
private void upload(HttpFormFile fFile, string key, string token, UploadOptions uploadOptions, UpCompletionHandler upCompletionHandler) { if (uploadOptions == null) { uploadOptions = UploadOptions.defaultOptions(); } Dictionary <string, string> vPostParams = new Dictionary <string, string>(); //设置key if (!string.IsNullOrEmpty(key)) { vPostParams.Add("key", key); } //设置token vPostParams.Add("token", token); //设置crc32校验 if (uploadOptions.CheckCrc32) { switch (fFile.BodyType) { case HttpFileType.DATA_SLICE: vPostParams.Add("crc32", string.Format("{0}", CRC32.CheckSumSlice(fFile.BodyBytes, fFile.Offset, fFile.Count))); break; case HttpFileType.DATA_BYTES: vPostParams.Add("crc32", string.Format("{0}", CRC32.CheckSumBytes(fFile.BodyBytes))); break; case HttpFileType.FILE_STREAM: long streamLength = fFile.BodyStream.Length; byte[] buffer = new byte[streamLength]; int cnt = fFile.BodyStream.Read(buffer, 0, (int)streamLength); vPostParams.Add("crc32", string.Format("{0}", CRC32.CheckSumSlice(buffer, 0, cnt))); fFile.BodyStream.Seek(0, SeekOrigin.Begin); break; case HttpFileType.FILE_PATH: vPostParams.Add("crc32", string.Format("{0}", CRC32.CheckSumFile(fFile.BodyFile))); break; } } //设置MimeType // FIX: (添加了下一行代码) // 修正上传文件MIME总为octect-stream(原因:未初始化FormFile.ContentType)的问题 // @fengyh 2016-08-17 14:50 fFile.ContentType = uploadOptions.MimeType; //设置扩展参数 foreach (KeyValuePair <string, string> kvp in uploadOptions.ExtraParams) { vPostParams.Add(kvp.Key, kvp.Value); } //设置进度处理和取消信号 ProgressHandler fUpProgressHandler = new ProgressHandler(delegate(long bytesWritten, long totalBytes) { double percent = (double)bytesWritten / totalBytes; //这样做是为了等待回复 if (percent > 0.95) { percent = 0.95; } uploadOptions.ProgressHandler(key, percent); }); CancellationSignal fCancelSignal = new CancellationSignal(delegate() { return(uploadOptions.CancellationSignal()); }); //第一次失败后使用备用域名重试一次 CompletionHandler fUpCompletionHandler = new CompletionHandler(delegate(ResponseInfo respInfo, string response) { Console.WriteLine("form upload result, {0}", respInfo.StatusCode); if (respInfo.needRetry()) { if (fFile.BodyStream != null) { fFile.BodyStream.Seek(0, SeekOrigin.Begin); } CompletionHandler retried = new CompletionHandler(delegate(ResponseInfo retryRespInfo, string retryResponse) { Console.WriteLine("form upload retry result, {0}", retryRespInfo.StatusCode); if (respInfo.isOk()) { uploadOptions.ProgressHandler(key, 1.0); } if (fFile.BodyStream != null) { fFile.BodyStream.Close(); } if (upCompletionHandler != null) { try { upCompletionHandler(key, retryRespInfo, retryResponse); } catch (Exception ex) { Console.WriteLine("form upload retry completion error, {0}", ex.Message); } } }); this.mHttpManager.postMultipartDataForm(Config.ZONE.UploadHost, null, vPostParams, fFile, fUpProgressHandler, retried); } else { if (respInfo.isOk()) { uploadOptions.ProgressHandler(key, 1.0); } if (fFile.BodyStream != null) { fFile.BodyStream.Close(); } if (upCompletionHandler != null) { try { upCompletionHandler(key, respInfo, response); } catch (Exception ex) { Console.WriteLine("form upload completion error, {0}", ex.Message); } } } }); this.mHttpManager.postMultipartDataForm(Config.ZONE.UploadHost, null, vPostParams, fFile, fUpProgressHandler, fUpCompletionHandler); }