Exemple #1
0
        /// <summary>
        /// 初始化上传任务
        /// </summary>
        /// <param name="upToken">上传凭证</param>
        /// <param name="encodedObjectName">Base64编码后的资源名</param>
        /// <returns>此操作执行后的返回结果</returns>
        private HttpResult initReq(string encodedObjectName, string upToken)
        {
            HttpResult result = new HttpResult();

            try
            {
                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}/buckets/{1}/objects/{2}/uploads", uploadHost, bucket, encodedObjectName);
                string upTokenStr = string.Format("UpToken {0}", upToken);
                result = httpManager.PostText(url, null, upTokenStr);
            }
            catch (Exception ex)
            {
                StringBuilder sb = new StringBuilder();
                sb.AppendFormat("[{0}] mkfile 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="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>
        /// 根据已上传的所有分片数据创建文件
        /// </summary>
        /// <param name="fileName">源文件名</param>
        /// <param name="size">文件大小</param>
        /// <param name="key">要保存的文件名</param>
        /// <param name="contexts">所有数据块的Context</param>
        /// <param name="upToken">上传凭证</param>
        /// <param name="putExtra">用户指定的额外参数</param>
        /// <returns>此操作执行后的返回结果</returns>
        private HttpResult MakeFile(string fileName, long size, string key, string upToken, PutExtra putExtra, string[] contexts)
        {
            HttpResult result = new HttpResult();

            try
            {
                string fnameStr    = "fname";
                string mimeTypeStr = "";
                string keyStr      = "";
                string paramStr    = "";
                //check file name
                if (!string.IsNullOrEmpty(fileName))
                {
                    fnameStr = string.Format("/fname/{0}", Base64.UrlSafeBase64Encode(fileName));
                }

                //check mime type
                if (!string.IsNullOrEmpty(putExtra.MimeType))
                {
                    mimeTypeStr = string.Format("/mimeType/{0}", Base64.UrlSafeBase64Encode(putExtra.MimeType));
                }

                //check key
                if (!string.IsNullOrEmpty(key))
                {
                    keyStr = string.Format("/key/{0}", Base64.UrlSafeBase64Encode(key));
                }

                //check extra params
                if (putExtra.Params != null && putExtra.Params.Count > 0)
                {
                    StringBuilder sb = new StringBuilder();
                    foreach (var kvp in putExtra.Params)
                    {
                        string k = kvp.Key;
                        string v = kvp.Value;
                        if (k.StartsWith("x:") && !string.IsNullOrEmpty(v))
                        {
                            sb.AppendFormat("/{0}/{1}", k, v);
                        }
                    }

                    paramStr = sb.ToString();
                }

                //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}/mkfile/{1}{2}{3}{4}{5}", uploadHost, size, mimeTypeStr, fnameStr, keyStr, paramStr);
                string body       = string.Join(",", contexts);
                string upTokenStr = string.Format("UpToken {0}", upToken);

                result = httpManager.PostText(url, body, upTokenStr);
            }
            catch (Exception ex)
            {
                StringBuilder sb = new StringBuilder();
                sb.AppendFormat("[{0}] mkfile 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);
        }
Exemple #4
0
        /// <summary>
        /// 上传数据流
        /// </summary>
        /// <param name="stream">(确定长度的)数据流</param>
        /// <param name="key">要保存的key</param>
        /// <param name="token">上传凭证</param>
        /// <param name="putExtra">上传可选设置</param>
        /// <returns>上传数据流后的返回结果</returns>
        public HttpResult UploadStream(Stream stream, string key, string token, PutExtra putExtra)
        {
            if (putExtra == null)
            {
                putExtra = new PutExtra();
            }
            if (string.IsNullOrEmpty(putExtra.MimeType))
            {
                putExtra.MimeType = "application/octet-stream";
            }
            if (putExtra.ProgressHandler == null)
            {
                putExtra.ProgressHandler = DefaultUploadProgressHandler;
            }
            if (putExtra.UploadController == null)
            {
                putExtra.UploadController = DefaultUploadController;
            }
            string fname = key;

            if (string.IsNullOrEmpty(key))
            {
                fname = "fname_temp";
            }

            HttpResult result = new HttpResult();

            try
            {
                string        boundary    = HttpManager.CreateFormDataBoundary();
                StringBuilder bodyBuilder = new StringBuilder();
                bodyBuilder.AppendLine("--" + boundary);

                if (key != null)
                {
                    //write key when it is not null
                    bodyBuilder.AppendLine("Content-Disposition: form-data; name=\"key\"");
                    bodyBuilder.AppendLine();
                    bodyBuilder.AppendLine(key);
                    bodyBuilder.AppendLine("--" + boundary);
                }

                //write token
                bodyBuilder.AppendLine("Content-Disposition: form-data; name=\"token\"");
                bodyBuilder.AppendLine();
                bodyBuilder.AppendLine(token);
                bodyBuilder.AppendLine("--" + boundary);

                //write extra params
                if (putExtra.Params != null && putExtra.Params.Count > 0)
                {
                    foreach (var p in putExtra.Params)
                    {
                        if (p.Key.StartsWith("x:"))
                        {
                            bodyBuilder.AppendFormat("Content-Disposition: form-data; name=\"{0}\"", p.Key);
                            bodyBuilder.AppendLine();
                            bodyBuilder.AppendLine();
                            bodyBuilder.AppendLine(p.Value);
                            bodyBuilder.AppendLine("--" + boundary);
                        }
                    }
                }

                //prepare data buffer
                int    bufferSize = 1024 * 1024;
                byte[] buffer     = new byte[bufferSize];
                int    bytesRead  = 0;
                putExtra.ProgressHandler(0, stream.Length);
                MemoryStream dataMS = new MemoryStream();
                while ((bytesRead = stream.Read(buffer, 0, bufferSize)) != 0)
                {
                    dataMS.Write(buffer, 0, bytesRead);
                }

                //write crc32
                uint crc32 = CRC32.CheckSumBytes(dataMS.ToArray());
                //write key when it is not null
                bodyBuilder.AppendLine("Content-Disposition: form-data; name=\"crc32\"");
                bodyBuilder.AppendLine();
                bodyBuilder.AppendLine(crc32.ToString());
                bodyBuilder.AppendLine("--" + boundary);

                //write fname
                bodyBuilder.AppendFormat("Content-Disposition: form-data; name=\"file\"; filename=\"{0}\"", fname);
                bodyBuilder.AppendLine();

                //write mime type
                bodyBuilder.AppendFormat("Content-Type: {0}", putExtra.MimeType);
                bodyBuilder.AppendLine();
                bodyBuilder.AppendLine();

                //write file data
                StringBuilder bodyEnd = new StringBuilder();
                bodyEnd.AppendLine();
                bodyEnd.AppendLine("--" + boundary + "--");

                byte[] partData1 = Encoding.UTF8.GetBytes(bodyBuilder.ToString());
                byte[] partData2 = dataMS.ToArray();
                byte[] partData3 = Encoding.UTF8.GetBytes(bodyEnd.ToString());

                MemoryStream ms = new MemoryStream();
                ms.Write(partData1, 0, partData1.Length);
                ms.Write(partData2, 0, partData2.Length);
                ms.Write(partData3, 0, partData3.Length);

                //get upload host
                string ak     = UpToken.GetAccessKeyFromUpToken(token);
                string bucket = UpToken.GetBucketFromUpToken(token);
                if (ak == null || bucket == null)
                {
                    return(HttpResult.InvalidToken);
                }

                string uploadHost = this.config.UpHost(ak, bucket);
                putExtra.ProgressHandler(stream.Length / 5, stream.Length);
                result = httpManager.PostMultipart(uploadHost, ms.ToArray(), boundary, null);
                putExtra.ProgressHandler(stream.Length, stream.Length);
                if (result.Code == (int)HttpCode.OK)
                {
                    result.RefText += string.Format("[{0}] [FormUpload] Uploaded: #STREAM# ==> \"{1}\"\n",
                                                    DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.ffff"), key);
                }
                else
                {
                    result.RefText += string.Format("[{0}] [FormUpload] Failed: code = {1}, text = {2}\n",
                                                    DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.ffff"), result.Code, result.Text);
                }

                //close memory stream
                ms.Close();
                dataMS.Close();
            }
            catch (Exception ex)
            {
                StringBuilder sb = new StringBuilder();
                sb.AppendFormat("[{0}] [FormUpload] 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();
                }
            }
            finally
            {
                if (stream != null)
                {
                    try
                    {
                        stream.Close();
                        stream.Dispose();
                    }
                    catch (Exception) { }
                }
            }

            return(result);
        }
        /// <summary>
        ///     上传数据流
        /// </summary>
        /// <param name="stream">(确定长度的)数据流</param>
        /// <param name="key">要保存的key</param>
        /// <param name="token">上传凭证</param>
        /// <param name="putExtra">上传可选设置</param>
        /// <returns>上传数据流后的返回结果</returns>
        public async Task <HttpResult> UploadStream(Stream stream, string key, string token, PutExtra putExtra)
        {
            if (putExtra == null)
            {
                putExtra = new PutExtra();
            }

            if (string.IsNullOrEmpty(putExtra.MimeType))
            {
                putExtra.MimeType = ContentType.APPLICATION_OCTET_STREAM;
            }

            if (putExtra.ProgressHandler == null)
            {
                putExtra.ProgressHandler = DefaultUploadProgressHandler;
            }

            if (putExtra.UploadController == null)
            {
                putExtra.UploadController = DefaultUploadController;
            }

            var fileName = key;

            if (string.IsNullOrEmpty(key))
            {
                fileName = "fname_temp";
            }

            var result = new HttpResult();

            try
            {
                var boundary = HttpManager.CreateFormDataBoundary();
                var content  = new MultipartFormDataContent(boundary);
                var length   = stream.Length;
                putExtra.ProgressHandler(0, length);

                // Key
                if (!string.IsNullOrEmpty(key))
                {
                    content.Add(new StringContent(key), "key");
                }

                // Token
                content.Add(new StringContent(token), "token");

                // Other params
                if (putExtra.Params != null)
                {
                    foreach (var param in putExtra.Params)
                    {
                        content.Add(new StringContent(param.Value), param.Key);
                    }
                }

                // Reuse stream
                if (!stream.CanSeek)
                {
                    var ms = new MemoryStream((int)stream.Length);
                    stream.CopyTo(ms);
                    stream.Dispose();
                    stream = ms;
                }

                // CRC32
                var crc32 = Crc32.CheckSumStream(stream);
                stream.Seek(0, SeekOrigin.Begin);
                content.Add(new StringContent(crc32.ToString()), "crc32");

                // Primary content
                var part = new StreamContent(stream);
                part.Headers.ContentType = MediaTypeHeaderValue.Parse(putExtra.MimeType);
                content.Add(part, "file", fileName);

                // Get upload host
                var ak     = UpToken.GetAccessKeyFromUpToken(token);
                var bucket = UpToken.GetBucketFromUpToken(token);
                if (ak == null || bucket == null)
                {
                    return(HttpResult.InvalidToken);
                }

                var uploadHost = await _config.UpHost(ak, bucket);

                // TODO: Real progress
                putExtra.ProgressHandler(length / 5, length);
                result = await _httpManager.PostAsync(uploadHost, content, boundary);

                putExtra.ProgressHandler(length, length);
                if (result.Code == (int)HttpCode.OK)
                {
                    result.RefText += $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.ffff}] [FormUpload] Uploaded: #STREAM# ==> \"{key}\"\n";
                }
                else
                {
                    result.RefText += $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.ffff}] [FormUpload] Failed: code = {result.Code}, text = {result.Text}\n";
                }
            }
            catch (Exception ex)
            {
                var sb = new StringBuilder();
                sb.Append($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.ffff}] [FormUpload] Error: ");
                var e = ex;
                while (e != null)
                {
                    sb.Append(e.Message + " ");
                    e = e.InnerException;
                }

                sb.AppendLine();

                if (ex is QiniuException qex)
                {
                    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();
        }
Exemple #7
0
        /// <summary>
        ///     根据已上传的所有分片数据创建文件
        /// </summary>
        /// <param name="fileName">源文件名</param>
        /// <param name="size">文件大小</param>
        /// <param name="key">要保存的文件名</param>
        /// <param name="contexts">所有数据块的Context</param>
        /// <param name="upToken">上传凭证</param>
        /// <param name="putExtra">用户指定的额外参数</param>
        /// <returns>此操作执行后的返回结果</returns>
        private async Task <HttpResult> MakeFile(string fileName, long size, string key, string upToken, PutExtra putExtra, string[] contexts)
        {
            var result = new HttpResult();

            try
            {
                var fnameStr    = "fname";
                var mimeTypeStr = "";
                var keyStr      = "";
                var paramStr    = "";
                //check file name
                if (!string.IsNullOrEmpty(fileName))
                {
                    fnameStr = $"/fname/{Base64.UrlSafeBase64Encode(fileName)}";
                }

                //check mime type
                if (!string.IsNullOrEmpty(putExtra.MimeType))
                {
                    mimeTypeStr = $"/mimeType/{Base64.UrlSafeBase64Encode(putExtra.MimeType)}";
                }

                //check key
                if (!string.IsNullOrEmpty(key))
                {
                    keyStr = $"/key/{Base64.UrlSafeBase64Encode(key)}";
                }

                //check extra params
                if (putExtra.Params != null && putExtra.Params.Count > 0)
                {
                    var sb = new StringBuilder();
                    foreach (var kvp in putExtra.Params)
                    {
                        var k = kvp.Key;
                        var v = kvp.Value;
                        if (k.StartsWith("x:") && !string.IsNullOrEmpty(v))
                        {
                            sb.Append($"/{k}/{v}");
                        }
                    }

                    paramStr = sb.ToString();
                }

                //get upload host
                var ak     = UpToken.GetAccessKeyFromUpToken(upToken);
                var bucket = UpToken.GetBucketFromUpToken(upToken);
                if (ak == null || bucket == null)
                {
                    return(HttpResult.InvalidToken);
                }

                var uploadHost = await _config.UpHost(ak, bucket);

                var url        = $"{uploadHost}/mkfile/{size}{mimeTypeStr}{fnameStr}{keyStr}{paramStr}";
                var body       = string.Join(",", contexts);
                var upTokenStr = $"UpToken {upToken}";

                result = await _httpManager.PostTextAsync(url, body, upTokenStr);
            }
            catch (Exception ex)
            {
                var sb = new StringBuilder();
                sb.Append($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.ffff}] mkfile Error: ");
                var e = ex;
                while (e != null)
                {
                    sb.Append(e.Message + " ");
                    e = e.InnerException;
                }

                sb.AppendLine();

                if (ex is QiniuException qex)
                {
                    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);
        }
Exemple #8
0
        /// <summary>
        ///     创建块(携带首片数据),同时检查CRC32
        /// </summary>
        /// <param name="resumeBlockerObj">创建分片上次的块请求</param>
        private async Task MakeBlock(object resumeBlockerObj)
        {
            var resumeBlocker    = (ResumeBlocker)resumeBlockerObj;
            var doneEvent        = resumeBlocker.DoneEvent;
            var blockMakeResults = resumeBlocker.BlockMakeResults;
            var putExtra         = resumeBlocker.PutExtra;
            var blockIndex       = resumeBlocker.BlockIndex;
            var result           = new HttpResult();

            //check whether to cancel
            while (true)
            {
                var upCtl = resumeBlocker.PutExtra.UploadController();
                if (upCtl == UploadControllerAction.Suspended)
                {
                    doneEvent.WaitOne(1000);
                }
                else if (upCtl == UploadControllerAction.Aborted)
                {
                    doneEvent.Set();

                    result.Code     = (int)HttpCode.USER_CANCELED;
                    result.RefCode  = (int)HttpCode.USER_CANCELED;
                    result.RefText += $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.ffff}] [ResumableUpload] Info: upload task is aborted, mkblk {blockIndex}\n";
                    blockMakeResults.Add(blockIndex, result);
                    return;
                }
                else
                {
                    break;
                }
            }

            var blockBuffer = resumeBlocker.BlockBuffer;
            var blockSize   = blockBuffer.Length;

            var upToken           = resumeBlocker.UploadToken;
            var uploadedBytesDict = resumeBlocker.UploadedBytesDict;
            var fileSize          = resumeBlocker.FileSize;
            var progressLock      = resumeBlocker.ProgressLock;
            var resumeInfo        = resumeBlocker.ResumeInfo;

            try
            {
                //get upload host
                var ak     = UpToken.GetAccessKeyFromUpToken(upToken);
                var bucket = UpToken.GetBucketFromUpToken(upToken);
                if (ak == null || bucket == null)
                {
                    result = HttpResult.InvalidToken;
                    doneEvent.Set();
                    return;
                }

                var uploadHost = await _config.UpHost(ak, bucket);

                var url        = $"{uploadHost}/mkblk/{blockSize}";
                var upTokenStr = $"UpToken {upToken}";
                using (var ms = new MemoryStream(blockBuffer, 0, blockSize))
                {
                    var data = ms.ToArray();

                    result = await _httpManager.PostDataAsync(url, data, token : upTokenStr);

                    if (result.Code == (int)HttpCode.OK)
                    {
                        var rc = JsonConvert.DeserializeObject <ResumeContext>(result.Text);

                        if (rc.Crc32 > 0)
                        {
                            var crc1 = rc.Crc32;
                            var crc2 = Crc32.CheckSumSlice(blockBuffer, 0, blockSize);
                            if (crc1 != crc2)
                            {
                                result.RefCode  = (int)HttpCode.USER_NEED_RETRY;
                                result.RefText += $" CRC32: remote={crc1}, local={crc2}\n";
                            }
                            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 += $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.ffff}] JSON Decode Error: text = {result.Text}";
                            result.RefCode  = (int)HttpCode.USER_NEED_RETRY;
                        }
                    }
                    else
                    {
                        result.RefCode = (int)HttpCode.USER_NEED_RETRY;
                    }
                }
            }
            catch (Exception ex)
            {
                var sb = new StringBuilder();
                sb.Append($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.ffff}] mkblk Error: ");
                var e = ex;
                while (e != null)
                {
                    sb.Append(e.Message + " ");
                    e = e.InnerException;
                }

                sb.AppendLine();

                if (ex is QiniuException qex)
                {
                    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();
        }
Exemple #9
0
        /// <summary>
        /// 根据已上传的所有分片数据创建文件
        /// </summary>
        /// <param name="fileName">源文件名</param>
        /// <param name="resumeInfo">分片上传记录信息</param>
        /// <param name="key">要保存的文件名</param>
        /// <param name="upToken">上传凭证</param>
        /// <param name="putExtra">用户指定的额外参数</param>
        /// <param name="encodedObjectName">Base64编码后的资源名</param>
        /// <returns>此操作执行后的返回结果</returns>
        private HttpResult completeParts(string fileName, ResumeInfo resumeInfo, string key, string upToken, PutExtra putExtra, string encodedObjectName)
        {
            HttpResult result = new HttpResult();

            try
            {
                string paramStr = "{}";
                if (string.IsNullOrEmpty(fileName))
                {
                    fileName = "fname";
                }
                if (string.IsNullOrEmpty(putExtra.MimeType))
                {
                    putExtra.MimeType = "";
                }
                if (string.IsNullOrEmpty(key))
                {
                    key = "";
                }
                if (putExtra.Params != null)
                {
                    paramStr = JsonConvert.SerializeObject(putExtra.Params);
                }
                //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 upTokenStr = string.Format("UpToken {0}", upToken);
                Dictionary <string, object> body = new Dictionary <string, object>();
                body.Add("fname", fileName);
                body.Add("mimeType", putExtra.MimeType);
                body.Add("customVars", null);
                body.Add("parts", resumeInfo.Etags);
                string url     = string.Format("{0}/buckets/{1}/objects/{2}/uploads/{3}", uploadHost, bucket, encodedObjectName, resumeInfo.UploadId);
                string bodyStr = JsonConvert.SerializeObject(body);
                result = httpManager.PostJson(url, bodyStr, upTokenStr);
            }
            catch (Exception ex)
            {
                StringBuilder sb = new StringBuilder();
                sb.AppendFormat("[{0}] completeParts 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);
        }