Example #1
0
        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);
            }));
        }
Example #2
0
        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);
        }