Esempio n. 1
0
        public B2StorageProvider(IConfiguration config, ILogger <B2StorageProvider> logger)
        {
            _b2Options = new B2Options()
            {
                AccountId      = config["Auth:B2:AccountId"],
                KeyId          = config["Auth:B2:KeyId"],
                ApplicationKey = config["Auth:B2:AppKey"],
                BucketId       = config["Auth:B2:BucketId"],
                PersistBucket  = true
            };

            // if backblaze isn't fully configured
            if (string.IsNullOrEmpty(_b2Options.AccountId) ||
                string.IsNullOrEmpty(_b2Options.KeyId) ||
                string.IsNullOrEmpty(_b2Options.ApplicationKey) ||
                string.IsNullOrEmpty(_b2Options.BucketId))
            {
                throw new InvalidOperationException("Backblaze not fully configured.");
            }

            _client = new B2Client(B2Client.Authorize(_b2Options));
            _logger = logger;

            _bucketName = _client.Buckets.GetList().Result
                          .Single(b => b.BucketId == _b2Options.BucketId)
                          .BucketName;
        }
        public static HttpRequestMessage GetDownloadAuthorization(B2Options options, string fileNamePrefix, int validDurationInSeconds, string bucketId, string b2ContentDisposition = "")
        {
            var uri = new Uri(options.ApiUrl + "/b2api/" + Constants.Version + "/" + Endpoints.GetDownloadAuthorization);

            var body = "{\"bucketId\":" + JsonConvert.ToString(bucketId) + ", \"fileNamePrefix\":" +
                       JsonConvert.ToString(fileNamePrefix) + ", \"validDurationInSeconds\":" +
                       JsonConvert.ToString(validDurationInSeconds);

            if (!string.IsNullOrEmpty(b2ContentDisposition))
            {
                body += ", \"b2ContentDisposition\":" + JsonConvert.ToString(b2ContentDisposition);
            }
            body += "}";

            var request = new HttpRequestMessage()
            {
                Method     = HttpMethod.Post,
                RequestUri = uri,
                Content    = new StringContent(body)
            };

            request.Headers.TryAddWithoutValidation("Authorization", options.AuthorizationToken);

            return(request);
        }
        public static HttpRequestMessage CopyPart(B2Options options, string sourceFileId, string destinationLargeFileId, int destinationPartNumber, string range = "")
        {
            var uri     = new Uri(options.ApiUrl + "/b2api/" + Constants.Version + "/" + Endpoints.CopyPart);
            var payload = new Dictionary <string, string>()
            {
                { "sourceFileId", sourceFileId },
                { "largeFileId", destinationLargeFileId },
                { "partNumber", destinationPartNumber.ToString() },
            };

            if (!string.IsNullOrWhiteSpace(range))
            {
                payload.Add("range", range);
            }
            var content = JsonConvert.SerializeObject(payload);
            var request = new HttpRequestMessage()
            {
                Method     = HttpMethod.Post,
                RequestUri = uri,
                Content    = new StringContent(content),
            };

            request.Headers.TryAddWithoutValidation("Authorization", options.AuthorizationToken);

            request.Content.Headers.ContentType   = new MediaTypeHeaderValue("application/json");
            request.Content.Headers.ContentLength = content.Length;

            return(request);
        }
        /// <summary>
        /// Upload a file to B2. This method will calculate the SHA1 checksum before sending any data.
        /// </summary>
        /// <param name="options"></param>
        /// <param name="uploadUrl"></param>
        /// <param name="fileData"></param>
        /// <param name="fileName"></param>
        /// <param name="fileInfo"></param>
        /// <returns></returns>
        public static HttpRequestMessage Upload(B2Options options, byte[] fileData, int partNumber, B2UploadPartUrl uploadPartUrl)
        {
            if (partNumber < 1 || partNumber > 10000)
            {
                throw new Exception("Part number must be between 1 and 10,000");
            }

            var uri     = new Uri(uploadPartUrl.UploadUrl);
            var request = new HttpRequestMessage()
            {
                Method     = HttpMethod.Post,
                RequestUri = uri,
                Content    = new ByteArrayContent(fileData)
            };

            // Get the file checksum
            string hash = Utilities.GetSHA1Hash(fileData);

            // Add headers
            request.Headers.Add("Authorization", uploadPartUrl.AuthorizationToken);
            request.Headers.Add("X-Bz-Part-Number", partNumber.ToString());
            request.Headers.Add("X-Bz-Content-Sha1", hash);
            request.Content.Headers.ContentLength = fileData.Length;

            return(request);
        }
        /// <summary>
        /// Upload a file to B2. This method will calculate the SHA1 checksum before sending any data.
        /// </summary>
        /// <param name="options"></param>
        /// <param name="uploadUrl"></param>
        /// <param name="fileData"></param>
        /// <param name="fileName"></param>
        /// <param name="fileInfo"></param>
        /// <returns></returns>
        public static HttpRequestMessage Upload(B2Options options, string uploadUrl, byte[] fileData, string fileName, Dictionary <string, string> fileInfo)
        {
            var uri     = new Uri(uploadUrl);
            var request = new HttpRequestMessage()
            {
                Method     = HttpMethod.Post,
                RequestUri = uri,
                Content    = new ByteArrayContent(fileData)
            };

            // Get the file checksum
            string hash = Utilities.GetSHA1Hash(fileData);

            // Add headers
            request.Headers.Add("Authorization", options.UploadAuthorizationToken);
            request.Headers.Add("X-Bz-File-Name", fileName.b2UrlEncode());
            request.Headers.Add("X-Bz-Content-Sha1", hash);
            // File Info headers
            if (fileInfo != null && fileInfo.Count > 0)
            {
                foreach (var info in fileInfo.Take(10))
                {
                    request.Headers.Add($"X-Bz-Info-{info.Key}", info.Value);
                }
            }
            // TODO last modified
            //request.Headers.Add("X-Bz-src_last_modified_millis", hash);

            request.Content.Headers.ContentType   = new MediaTypeHeaderValue("b2/x-auto");
            request.Content.Headers.ContentLength = fileData.Length;

            return(request);
        }
Esempio n. 6
0
        /// <summary>
        /// Used to modify the bucket type of the provided bucket.
        /// </summary>
        /// <param name="options"></param>
        /// <returns></returns>
        public static HttpRequestMessage UpdateBucket(B2Options options, string bucketId, string bucketType)
        {
            var body = "{\"accountId\":\"" + options.AccountId + "\", \"bucketId\":\"" + bucketId + "\", \"bucketType\":\"" +
                       bucketType + "\"}";

            return(BaseRequestGenerator.PostRequest(Endpoints.Update, body, options));
        }
Esempio n. 7
0
        /// <summary>
        /// Upload a file to B2 using a stream. NOTE: You MUST provide the SHA1 at the end of your stream. This method will NOT do it for you.
        /// </summary>
        /// <param name="options"></param>
        /// <param name="uploadUrl"></param>
        /// <param name="fileData"></param>
        /// <param name="fileName"></param>
        /// <param name="fileInfo"></param>
        /// <returns></returns>
        public static HttpRequestMessage Upload(B2Options options, string uploadUrl, Stream fileDataWithSHA, string fileName, Dictionary <string, string> fileInfo, string contentType = "", bool dontSHA = false)
        {
            var uri     = new Uri(uploadUrl);
            var request = new HttpRequestMessage()
            {
                Method     = HttpMethod.Post,
                RequestUri = uri,
                Content    = new StreamContent(fileDataWithSHA)
            };

            // Add headers
            request.Headers.TryAddWithoutValidation("Authorization", options.UploadAuthorizationToken);
            request.Headers.Add("X-Bz-File-Name", fileName.b2UrlEncode());
            // Stream puts the SHA1 at the end of the content
            request.Headers.Add("X-Bz-Content-Sha1", dontSHA ? "do_not_verify" : "hex_digits_at_end");
            // File Info headers
            if (fileInfo != null && fileInfo.Count > 0)
            {
                foreach (var info in fileInfo.Take(10))
                {
                    request.Headers.Add($"X-Bz-Info-{info.Key}", info.Value);
                }
            }
            // TODO last modified
            //request.Headers.Add("X-Bz-src_last_modified_millis", hash);

            request.Content.Headers.ContentType = new MediaTypeHeaderValue(string.IsNullOrWhiteSpace(contentType) ? "b2/x-auto" : contentType);
            // SHA will be in Stream already
            request.Content.Headers.ContentLength = fileDataWithSHA.Length;

            return(request);
        }
Esempio n. 8
0
        public static HttpRequestMessage ListVersions(B2Options options, string bucketId, string startFileName = "", string startFileId = "", int?maxFileCount = null, string prefix = "", string delimiter = "")
        {
            var body = "{\"bucketId\":\"" + bucketId + "\"";

            if (!string.IsNullOrEmpty(startFileName))
            {
                body += ", \"startFileName\":" + JsonConvert.ToString(startFileName);
            }
            if (!string.IsNullOrEmpty(startFileId))
            {
                body += ", \"startFileId\":\"" + startFileId + "\"";
            }
            if (maxFileCount.HasValue)
            {
                body += ", \"maxFileCount\":" + maxFileCount.Value.ToString();
            }
            if (!string.IsNullOrEmpty(prefix))
            {
                body += ", \"prefix\":" + JsonConvert.ToString(prefix);
            }
            if (!string.IsNullOrEmpty(delimiter))
            {
                body += ", \"delimiter\":" + JsonConvert.ToString(delimiter);
            }
            body += "}";
            return(BaseRequestGenerator.PostRequest(Endpoints.Versions, body, options));
        }
        public static HttpRequestMessage Cancel(B2Options options, string fileId)
        {
            var content = JsonConvert.SerializeObject(new { fileId });
            var request = BaseRequestGenerator.PostRequestJson(Endpoints.Cancel, content, options);

            return(request);
        }
        public static HttpRequestMessage Finish(B2Options options, string fileId, string[] partSHA1Array)
        {
            var content = JsonConvert.SerializeObject(new { fileId, partSha1Array = partSHA1Array });
            var request = BaseRequestGenerator.PostRequestJson(Endpoints.Finish, content, options);

            return(request);
        }
Esempio n. 11
0
 public B2Client(B2Options options)
 {
     _options   = options;
     Buckets    = new Buckets(options);
     Files      = new Files(options);
     LargeFiles = new LargeFiles(options);
 }
Esempio n. 12
0
        public static HttpRequestMessage Start(B2Options options, string bucketId, string fileName, string contentType, Dictionary <string, string> fileInfo = null)
        {
            var uri     = new Uri(options.ApiUrl + "/b2api/" + Constants.Version + "/" + Endpoints.Start);
            var content = "{\"bucketId\":\"" + bucketId + "\",\"fileName\":\"" + fileName +
                          "\",\"contentType\":\"" + (string.IsNullOrEmpty(contentType) ? "b2/x-auto" : contentType) + "\"}";
            var request = new HttpRequestMessage()
            {
                Method     = HttpMethod.Post,
                RequestUri = uri,
                Content    = new StringContent(content),
            };

            request.Headers.Add("Authorization", options.AuthorizationToken);
            // File Info headers
            if (fileInfo != null && fileInfo.Count > 0)
            {
                foreach (var info in fileInfo.Take(10))
                {
                    request.Headers.Add($"X-Bz-Info-{info.Key}", info.Value);
                }
            }
            request.Content.Headers.ContentType   = new MediaTypeHeaderValue("application/json");
            request.Content.Headers.ContentLength = content.Length;

            return(request);
        }
Esempio n. 13
0
        /// <summary>
        /// Requires that AccountId and ApplicationKey on the options object be set. If you are using an application key you must specify the accountId, the keyId, and the applicationKey.
        /// </summary>
        /// <param name="options"></param>
        /// <returns></returns>
        public static B2Options Authorize(B2Options options)
        {
            // Return if already authenticated.
            if (options.Authenticated)
            {
                return(options);
            }

            var client = HttpClientFactory.CreateHttpClient(options.RequestTimeout);

            var requestMessage = AuthRequestGenerator.Authorize(options);
            var response       = client.SendAsync(requestMessage).Result;

            var jsonResponse = response.Content.ReadAsStringAsync().Result;

            if (response.IsSuccessStatusCode)
            {
                var authResponse = JsonConvert.DeserializeObject <B2AuthResponse>(jsonResponse);

                options.SetState(authResponse);
            }
            else if (response.StatusCode == HttpStatusCode.Unauthorized)
            {
                // Return a better exception because of confusing Keys api.
                throw new AuthorizationException("If you are using an Application key and not a Master key, make sure that you are supplying the Key ID and Key Value for that Application Key. Do not mix your Account ID with your Application Key.");
            }
            else
            {
                throw new AuthorizationException(jsonResponse);
            }

            return(options);
        }
Esempio n. 14
0
        /// <summary>
        /// Create a bucket. Defaults to allPrivate.
        /// </summary>
        /// <param name="options"></param>
        /// <param name="bucketName"></param>
        /// <param name="bucketType"></param>
        /// <returns></returns>
        public static HttpRequestMessage CreateBucket(B2Options options, string bucketName, B2BucketOptions bucketOptions)
        {
            // Check lifecycle rules
            var hasLifecycleRules = bucketOptions.LifecycleRules != null && bucketOptions.LifecycleRules.Count > 0;

            if (hasLifecycleRules)
            {
                foreach (var rule in bucketOptions.LifecycleRules)
                {
                    if (rule.DaysFromHidingToDeleting < 1 || rule.DaysFromUploadingToHiding < 1)
                    {
                        throw new System.Exception("The smallest number of days you can set in a lifecycle rule is 1.");
                    }
                    if (rule.DaysFromHidingToDeleting == null && rule.DaysFromUploadingToHiding == null)
                    {
                        throw new System.Exception("You must set either DaysFromHidingToDeleting or DaysFromUploadingToHiding. Both cannot be null.");
                    }
                }
            }

            var allowed = new Regex("^[a-zA-Z0-9-]+$");

            if (bucketName.Length < 6 || bucketName.Length > 50 || !allowed.IsMatch(bucketName) || bucketName.StartsWith("b2-"))
            {
                throw new Exception(@"The bucket name specified does not match the requirements. 
                            Bucket Name can consist of upper-case letters, lower-case letters, numbers, and "" - "", 
                            must be at least 6 characters long, and can be at most 50 characters long");
            }

            var body = new B2BucketCreateModel()
            {
                accountId  = options.AccountId,
                bucketName = bucketName,
                bucketType = bucketOptions.BucketType.ToString()
            };

            // Add optional options
            if (bucketOptions.CacheControl != 0)
            {
                body.bucketInfo = new Dictionary <string, string>()
                {
                    { "Cache-Control", "max-age=" + bucketOptions.CacheControl }
                };
            }
            if (hasLifecycleRules)
            {
                body.lifecycleRules = bucketOptions.LifecycleRules;
            }

            // Has cors rules
            if (bucketOptions.CORSRules != null && bucketOptions.CORSRules.Count > 0)
            {
                body.corsRules = bucketOptions.CORSRules;
            }

            var json = JsonSerialize(body);

            return(BaseRequestGenerator.PostRequest(Endpoints.Create, json, options));
        }
Esempio n. 15
0
 /// <summary>
 /// Only call this method if you created a B2Client with authorizeOnInitalize = false. This method of using B2.NET is considered in Beta, as it has not been extensively tested.
 /// </summary>
 /// <returns></returns>
 public async Task Initialize()
 {
     _options      = Authorize(_options);
     Buckets       = new Buckets(_options);
     Files         = new Files(_options);
     LargeFiles    = new LargeFiles(_options);
     _capabilities = _options.Capabilities;
 }
Esempio n. 16
0
        /// <summary>
        /// Create a bucket. Defaults to allPrivate.
        /// </summary>
        /// <param name="options"></param>
        /// <param name="bucketName"></param>
        /// <param name="bucketType"></param>
        /// <returns></returns>
        public static HttpRequestMessage CreateBucket(B2Options options, string bucketName, string bucketType = "allPrivate")
        {
            // TODO: Handle naming conventions, check name for invalid characters.
            var body = "{\"accountId\":\"" + options.AccountId + "\", \"bucketName\":\"" + bucketName +
                       "\", \"bucketType\":\"" + bucketType + "\"}";

            return(BaseRequestGenerator.PostRequest(Endpoints.Create, body, options));
        }
Esempio n. 17
0
 public B2Client(B2Options options)
 {
     _options      = Authorize(options);
     Buckets       = new Buckets(options);
     Files         = new Files(options);
     LargeFiles    = new LargeFiles(options);
     _capabilities = options.Capabilities;
 }
Esempio n. 18
0
 public BaseTest()
 {
     Options = new B2Options()
     {
         KeyId          = TestConstants.KeyId,
         ApplicationKey = TestConstants.ApplicationKey
     };
 }
Esempio n. 19
0
 public BaseTest()
 {
     Options = new B2Options()
     {
         AccountId      = TestConstants.AccountId,
         ApplicationKey = TestConstants.ApplicationKey,
         BucketId       = TestConstants.BucketId
     };
 }
Esempio n. 20
0
        public static string DetermineBucketId(B2Options options, string bucketId)
        {
            // Check for a persistant bucket
            if (!options.PersistBucket && string.IsNullOrEmpty(bucketId))
            {
                throw new ArgumentNullException(nameof(bucketId));
            }

            // Are we persisting buckets? If so use the one from settings
            return(options.PersistBucket ? options.BucketId : bucketId);
        }
        public static HttpRequestMessage ListParts(B2Options options, string fileId, int startPartNumber, int maxPartCount)
        {
            if (startPartNumber < 1 || startPartNumber > 10000)
            {
                throw new Exception("Start part number must be between 1 and 10,000");
            }

            var content = JsonConvert.SerializeObject(new { fileId, startPartNumber, maxPartCount });
            var request = BaseRequestGenerator.PostRequestJson(Endpoints.ListParts, content, options);

            return(request);
        }
        public static HttpRequestMessage DownloadByName(B2Options options, string bucketName, string fileName)
        {
            var uri     = new Uri(options.DownloadUrl + "/" + Endpoints.DownloadByName + "/" + bucketName + "/" + fileName.b2UrlEncode());
            var request = new HttpRequestMessage()
            {
                Method     = HttpMethod.Get,
                RequestUri = uri
            };

            request.Headers.Add("Authorization", options.AuthorizationToken);

            return(request);
        }
Esempio n. 23
0
        public static HttpRequestMessage Authorize(B2Options options)
        {
            var uri     = new Uri(Constants.ApiBaseUrl + "/" + Constants.Version + "/" + Endpoints.Auth);
            var request = new HttpRequestMessage()
            {
                Method     = HttpMethod.Get,
                RequestUri = uri
            };

            request.Headers.Add("Authorization", Utilities.CreateAuthorizationHeader(options.AccountId, options.ApplicationKey));

            return(request);
        }
        public static HttpRequestMessage DownloadById(B2Options options, string fileId)
        {
            var uri     = new Uri(options.DownloadUrl + "/b2api/" + Constants.Version + "/" + Endpoints.DownloadById);
            var request = new HttpRequestMessage()
            {
                Method     = HttpMethod.Post,
                RequestUri = uri,
                Content    = new StringContent("{\"fileId\":\"" + fileId + "\"}")
            };

            request.Headers.Add("Authorization", options.AuthorizationToken);

            return(request);
        }
Esempio n. 25
0
        public static HttpRequestMessage PostRequest(string endpoint, string body, B2Options options)
        {
            var uri     = new Uri(options.ApiUrl + "/b2api/" + Constants.Version + "/" + endpoint);
            var request = new HttpRequestMessage()
            {
                Method     = HttpMethod.Post,
                RequestUri = uri,
                Content    = new StringContent(body)
            };

            request.Headers.Add("Authorization", options.AuthorizationToken);

            return(request);
        }
Esempio n. 26
0
        /// <summary>
        /// Simple method for instantiating the B2Client. Does auth for you.
        /// </summary>
        /// <param name="accountId"></param>
        /// <param name="applicationkey"></param>
        /// <param name="requestTimeout"></param>
        public B2Client(string accountId, string applicationkey, int requestTimeout = 100)
        {
            _options = new B2Options()
            {
                AccountId      = accountId,
                ApplicationKey = applicationkey,
                RequestTimeout = requestTimeout
            };
            _options = Authorize(_options);

            Buckets    = new Buckets(_options);
            Files      = new Files(_options);
            LargeFiles = new LargeFiles(_options);
        }
Esempio n. 27
0
        public static HttpRequestMessage Copy(B2Options options, string sourceFileId, string fileName, B2MetadataDirective metadataDirective,
                                              string contentType = "", Dictionary <string, string> fileInfo = null, string range = "", string destinationBucketId = "")
        {
            var uri = new Uri(options.ApiUrl + "/b2api/" + Constants.Version + "/" + Endpoints.Copy);

            var payload = new Dictionary <string, object>()
            {
                { "sourceFileId", sourceFileId },
                { "fileName", fileName },
                { "metadataDirective", metadataDirective.ToString() },
            };

            if (!string.IsNullOrWhiteSpace(range))
            {
                payload.Add("range", range);
            }
            if (!string.IsNullOrWhiteSpace(destinationBucketId))
            {
                payload.Add("destinationBucketId", destinationBucketId);
            }
            if (metadataDirective == B2MetadataDirective.REPLACE)
            {
                if (string.IsNullOrWhiteSpace(contentType))
                {
                    payload.Add("contentType", "b2/x-auto");
                }
                else
                {
                    payload.Add("contentType", contentType);
                }
            }
            // File Info
            if (metadataDirective == B2MetadataDirective.REPLACE && fileInfo != null && fileInfo.Count > 0)
            {
                payload.Add("fileInfo", fileInfo);
            }
            var json = JsonConvert.SerializeObject(payload);

            var request = new HttpRequestMessage()
            {
                Method     = HttpMethod.Post,
                RequestUri = uri,
                Content    = new StringContent(json)
            };

            request.Headers.TryAddWithoutValidation("Authorization", options.AuthorizationToken);

            return(request);
        }
Esempio n. 28
0
        public static HttpRequestMessage HideFile(B2Options options, string bucketId, string fileName = "", string fileId = "")
        {
            var body = "{\"bucketId\":\"" + bucketId + "\"";

            if (!string.IsNullOrEmpty(fileName) && string.IsNullOrEmpty(fileId))
            {
                body += ", \"fileName\":" + JsonConvert.ToString(fileName);
            }
            if (!string.IsNullOrEmpty(fileId))
            {
                body += ", \"fileId\":\"" + fileId + "\"";
            }
            body += "}";
            return(BaseRequestGenerator.PostRequest(Endpoints.Hide, body, options));
        }
Esempio n. 29
0
        public static HttpRequestMessage GetList(B2Options options, string bucketId, string startFileName = "", int?maxFileCount = null)
        {
            var body = "{\"bucketId\":\"" + bucketId + "\"";

            if (!string.IsNullOrEmpty(startFileName))
            {
                body += ", \"startFileName\":" + JsonConvert.ToString(startFileName);
            }
            if (maxFileCount.HasValue)
            {
                body += ", \"maxFileCount\":" + maxFileCount.Value.ToString();
            }
            body += "}";
            return(BaseRequestGenerator.PostRequest(Endpoints.List, body, options));
        }
Esempio n. 30
0
        /// <summary>
        /// Create a bucket. Defaults to allPrivate.
        /// </summary>
        /// <param name="options"></param>
        /// <param name="bucketName"></param>
        /// <param name="bucketType"></param>
        /// <returns></returns>
        public static HttpRequestMessage CreateBucket(B2Options options, string bucketName, string bucketType = "allPrivate")
        {
            var allowed = new Regex("^[a-zA-Z0-9-]+$");

            if (bucketName.Length < 6 || bucketName.Length > 50 || !allowed.IsMatch(bucketName) || bucketName.StartsWith("b2-"))
            {
                throw new Exception(@"The bucket name specified does not match the requirements. 
                            Bucket Name can consist of upper-case letters, lower-case letters, numbers, and "" - "", 
                            must be at least 6 characters long, and can be at most 50 characters long");
            }

            var json = JsonConvert.SerializeObject(new { accountId = options.AccountId, bucketName, bucketType });

            return(BaseRequestGenerator.PostRequest(Endpoints.Create, json, options));
        }