コード例 #1
0
ファイル: BackblazeB2Client.cs プロジェクト: yvanam/SyncPro
        /// <summary>
        /// Upload a file to B2 in a single HTTP payload
        /// </summary>
        /// <param name="fileName">The full name of the file (including relative path)</param>
        /// <param name="sha1Hash">The 40-character SHA1 hash of the file's content</param>
        /// <param name="size">The size of the file in bytes</param>
        /// <param name="bucketId">The bucket ID of the bucket where the file will be uploaded</param>
        /// <param name="stream">The <see cref="Stream"/> that exposes the file content</param>
        /// <returns>(async) The file upload response</returns>
        /// <remarks>See https://www.backblaze.com/b2/docs/b2_upload_file.html for additional information</remarks>
        public async Task <BackblazeB2FileUploadResponse> UploadFile(
            string fileName,
            string sha1Hash,
            long size,
            string bucketId,
            Stream stream)
        {
            // Get the upload information (destination URL and temporary auth token)
            GetUploadUrlResponse uploadUrlResponse = await GetUploadUrl(bucketId);

            BackblazeB2FileUploadResponse uploadResponse;

            HttpRequestMessage request = CreateRequestMessage(
                HttpMethod.Post,
                uploadUrlResponse.UploadUrl);

            using (request)
            {
                // Add the authorization header for the temporary authorization token
                request.Headers.TryAddWithoutValidation(
                    "Authorization",
                    uploadUrlResponse.AuthorizationToken);

                // Add the B2 require headers. Note that the filename needs to be URL encoded
                request.Headers.Add(Constants.Headers.FileName, UrlEncode(fileName));
                request.Headers.Add(Constants.Headers.ContentSha1, sha1Hash);

                request.Content = new DelayedDisposeStreamContent(stream);

                // Set the content type to 'auto' where B2 will determine the content type
                request.Content.Headers.ContentType = new MediaTypeHeaderValue("b2/x-auto");

                HttpResponseMessage responseMessage =
                    await SendRequestAsync(request).ConfigureAwait(false);

                using (responseMessage)
                {
                    uploadResponse =
                        await responseMessage.Content.TryReadAsJsonAsync <BackblazeB2FileUploadResponse>();
                }
            }

            return(uploadResponse);
        }
コード例 #2
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="file"></param>
        /// <param name="hash"></param>
        /// <param name="data"></param>
        /// <returns>fileId</returns>
        private async Task <(byte[] encryptedHash, string fileId)> StoreFileAsync(string file, byte[] hash, byte[] data, bool preventEncryption = false)
        {
            async Task <GetUploadUrlResponse> GetUploadUrl(int attempts = 0)
            {
                if (AuthResp == null)
                {
                    AuthResp = await AuthorizeAccount();
                }
                Delay();
                try
                {
                    var urlresp = await AuthResp.apiUrl
                                  .AppendPathSegment("/b2api/v1/b2_get_upload_url")
                                  .WithHeaders(new { Authorization = AuthResp.authorizationToken })
                                  .PostJsonAsync(new { bucketId = BucketId })
                                  .ReceiveJson <GetUploadUrlResponse>().ConfigureAwait(false);

                    SuccessfulTransmission();
                    return(urlresp);
                }
                catch (FlurlHttpException ex)
                {
                    if (ex.Call.HttpStatus != null && ex.Call.HttpStatus == System.Net.HttpStatusCode.Unauthorized)
                    {
                        AuthResp = null;
                    }
                    else
                    {
                        // Other classes of errors may be congestion related so we increase the delay
                        FailedTransmission();
                    }
                    if (attempts < Retries)
                    {
                        return(await GetUploadUrl(attempts + 1).ConfigureAwait(false));
                    }
                    throw;
                }
            }

            var hashFileId = await UploadData();

            async Task <(byte[] encryptedHash, string fileId)> UploadData(int attempts = 0)
            {
                if (UploadUrlResp == null)
                {
                    UploadUrlResp = await GetUploadUrl();
                }
                Delay();
                try
                {
                    if (Encryptor != null && !preventEncryption)
                    {
                        data = Encryptor.EncryptBytes(data);
                        hash = HashTools.GetSHA1Hasher().ComputeHash(data);
                    }

                    var filecontent = new ByteArrayContent(data);
                    filecontent.Headers.Add("Content-Type", "application/octet-stream");
                    var uploadresp = await UploadUrlResp.uploadUrl
                                     .WithHeaders(new
                    {
                        Authorization     = UploadUrlResp.authorizationToken,
                        X_Bz_File_Name    = file,
                        Content_Length    = data.Length,
                        X_Bz_Content_Sha1 = HashTools.ByteArrayToHexViaLookup32(hash)
                    })
                                     .PostAsync(filecontent)
                                     .ReceiveJson <UploadResponse>().ConfigureAwait(false);

                    SuccessfulTransmission();
                    return(hash, uploadresp.fileId);
                }
                catch (FlurlHttpException ex)
                {
                    if (ex.Call.HttpStatus != null && ex.Call.HttpStatus == System.Net.HttpStatusCode.Unauthorized)
                    {
                        UploadUrlResp = null;
                    }
                    else
                    {
                        // Other classes of errors may be congestion related so we increase the delay
                        FailedTransmission();
                    }

                    if (attempts < Retries)
                    {
                        return(await UploadData(attempts + 1).ConfigureAwait(false));
                    }
                    throw;
                }
            }

            return(hashFileId);
        }