/// <summary> /// Call the B2 'Upload File' API (see https://www.backblaze.com/b2/docs/b2_upload_file.html) /// </summary> /// <param name="uploadUrl"></param> /// <param name="authorizationToken"></param> /// <param name="fileName"></param> /// <param name="contentType"></param> /// <param name="contentLength"></param> /// <param name="contentSha1"></param> /// <param name="fileInfo"></param> /// <param name="file"></param> /// <returns></returns> public async Task <UploadFileResponse> UploadFile(string uploadUrl, string authorizationToken, string fileName, string contentType, long contentLength, string contentSha1, Dictionary <string, string> attributes, Stream content) { if (attributes == null) { throw new ArgumentNullException("attributes"); } Trace(() => $"UploadFile: uploadUrl={uploadUrl}, authorizationToken={authorizationToken}, fileName={fileName}, contentType={contentType}, contentLength={contentLength}, contentSha1={contentSha1}, attributes={ToString(attributes)}"); var headers = (attributes.ToDictionary(a => $"X-Bz-Info-{a.Key}", a => a.Value)); headers["X-Bz-File-Name"] = B2UrlEncoder.Encode(fileName.Replace('\\', '/')); headers["Content-Type"] = contentType; headers["Content-Length"] = contentLength.ToString(); headers["X-Bz-Content-Sha1"] = contentSha1; var request = new HttpRequestMessage(HttpMethod.Post, uploadUrl) .WithAuthorization(authorizationToken) .WithContent(content) .WithContentHeaders(headers); var response = await httpClient.SendAsync(request).ConfigureAwait(false); var responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); ThrowIfFailure(response, responseStream); Trace(() => "UploadFile completed"); return(UploadFileResponse.FromJson(responseStream)); }
public void ShouldThrowOnInvalidAsciiCharacter() { Assert.That(() => B2UrlEncoder.Decode("abc\n"), Throws.Exception .TypeOf <ArgumentException>() .With.Message.EqualTo("Invalid URL encoded string 'abc\n' - invalid character '\n' at position 3")); }
public void ShouldThrowOn16BitCharacter() { Assert.That(() => B2UrlEncoder.Decode("abc\u263A"), Throws.Exception .TypeOf <ArgumentException>() .With.Message.EqualTo("Invalid URL encoded string 'abc\u263A': found 16-bit code point at position 3")); }
public void ShouldThrowOnTruncatedString() { Assert.That(() => B2UrlEncoder.Decode("%2"), Throws.Exception .TypeOf <ArgumentException>() .With.Message.EqualTo("Invalid URL encoded string '%2' - Expected hex digit but string was truncated")); }
public void ShouldThrowOnInvalidHexDigit() { Assert.That(() => B2UrlEncoder.Decode("%2!2"), Throws.Exception .TypeOf <ArgumentException>() .With.Message.EqualTo("Invalid URL encoded string '%2!2' at position 2 - Unable to parse '!' as a hex digit")); }
public void ShouldThrowOnEncodeInvalidHexDigit() { Assert.That(() => B2UrlEncoder.EncodeHexDigit(-1), Throws.Exception .TypeOf <ArgumentException>() .With.Message.EqualTo("Cannot convert integer -1 to hex digit")); }
public void UrlDecodeMinimal() { foreach (var testCase in testData.testCases) { var decoded = B2UrlEncoder.Decode(testCase.minimallyEncoded); Assert.AreEqual(testCase.s, decoded); } }
public async Task UploadFile(string sourcePath, string destinationPath, string contentType = "text/plain", IProgress <StreamProgress> checksumProgress = null, IProgress <StreamProgress> uploadProgress = null) { // Ensure the file cannot be altered whilst being uploaded. using (var fs = new FileStream(sourcePath, FileMode.Open, FileAccess.Read, FileShare.Read)) using (var qs = new ProgressReportingStream(fs)) { // The B2 HTTP api requires the SHA1 checksum before uploading; this means the file must be // read twice, doh! var e = new B2UrlEncoder(); var shaTask = Task.Run(() => SHA1.Create().ComputeHash(qs)); if (checksumProgress != null) { while (await Task.WhenAny(shaTask, Task.Delay(100)) != shaTask) { checksumProgress.Report(qs.Progress()); } } await shaTask; if (checksumProgress != null) { checksumProgress.Report(qs.Progress()); } var sha1hex = new StringBuilder(40); foreach (var b in shaTask.Result) { sha1hex.AppendFormat("{0:X2}", b); } qs.Position = 0; var getUploadUrlResponse = await b2api.GetUploadUrl(ApiUrl, AuthorizationToken, BucketId).ConfigureAwait(false); var url = getUploadUrlResponse.uploadUrl; var attributes = new Dictionary <string, string>(); var fileInfo = new FileInfo(sourcePath); attributes["last_modified_millis"] = fileInfo.LastWriteTimeUtc.ToUnixTimeMillis().ToString(); var uploadFileTask = b2api.UploadFile(url, getUploadUrlResponse.authorizationToken, destinationPath, contentType, fileInfo.Length, sha1hex.ToString(), attributes, qs); if (uploadProgress != null) { while (await Task.WhenAny(uploadFileTask, Task.Delay(100)) != uploadFileTask) { uploadProgress.Report(qs.Progress()); } } await uploadFileTask; if (uploadProgress != null) { uploadProgress.Report(qs.Progress()); } } }
public void UrlEncode() { foreach (var testCase in testData.testCases) { var encoded = B2UrlEncoder.Encode(testCase.s); var acceptableEncodings = new[] { testCase.minimallyEncoded, testCase.fullyEncoded }; Assert.Contains(encoded, acceptableEncodings); } }