c# - 如何验证 Azure 存储 blob 名称
问题描述
我正在实现一个 API 来在 Azure Blob 存储中存储文件。
我正在使用 Microsoft 库来验证容器和 blob 名称。
NameValidator.ValidateContainerName(containerName);
NameValidator.ValidateBlobName(blobFullName);
但是,它返回的一些名称是有效的,即使根据他们自己的文档我知道它们不是有效的,当我尝试保存它们时,blob 存储正如预期的那样返回 400 错误请求。因此,除了关于为什么 MS 验证库不完整的问题之外,我如何在 C# 中执行其余的验证?具体来说,我现在失败了
“一些 ASCII 或 Unicode 字符,如控制字符(0x00 到 0x1F、\u0081 等)”
我有一个文件名中带有 \u0081 的文件。剩余的无效字符是什么。他们将我们指向 ietf 文档,然后说“某些”字符是不允许的?哪个?只是所有控制字符?
为清楚起见,这里是返回 400 的部分
CloudBlockBlob blob = documentContainer.GetBlockBlobReference(blobFullName);
await blob.UploadFromStreamAsync(fileStream, token).ConfigureAwait(false);
谢谢你的帮助!
更新:我添加了一些逻辑来至少检查控制字符。如果我能得到一些强大的东西,我会针对微软的验证码发出 PR
if (blobFullName.ToCharArray().Any(c => Char.IsControl(c))) {
throw new HissyFitException(); // or do other stuff to fail validation
}
解决方案
我现在编写了自己的实现来检查存储帐户名称、容器名称和 blob 名称的有效性。在我的实现中,整个名称必须以如下形式传递给方法:Storage_Account_name/Container_name/Blob_name,例如 mystorageaccount/containername/this/is_a/blob.jpg Blob 名称可能包含“/”。
// Use like this:
public static bool IsBlobFilenameValid(string blobFilename)
{
// e. g. blobFilename = "mystorageaccount/containername/this/is_a/blob.jpg
string storageAccount = GetStorageAccount(blobFilename);
string container = GetContainer(blobFilename);
string blobName = GetBlobFilename(blobFilename);
if(string.IsNullOrWhiteSpace(storageAccount)
|| string.IsNullOrWhiteSpace(container)
|| string.IsNullOrWhiteSpace(blobName)
|| !IsAzureBlobFilenameValid(blobFilename))
{
return false;
}
return true;
}
private static bool IsAzureBlobFilenameValid(string filename)
{
if (filename.Count(c => c == '/') < 2)
{
return false;
}
var storageAccount = GetStorageAccount(filename);
var container = GetContainer(filename);
var blob = GetBlobFilename(filename);
string patternAccount = @"^[a-z0-9]{3,24}$";
string patternContainer = @"^[a-z0-9-]{3,63}$";
string patternBlob = @"^.{1,1024}$";
if (!Regex.IsMatch(container, patternContainer)
|| !Regex.IsMatch(storageAccount, patternAccount)
|| !Regex.IsMatch(blob, patternBlob))
{
return false;
}
return true;
}
private static string GetStorageAccount(string file)
{
int charLocation = file.IndexOf('/', StringComparison.Ordinal);
if (charLocation > 0)
{
return file.Substring(0, charLocation);
}
return string.Empty;
}
private static string GetContainer(string file)
{
int charLocation = IndexOfSecond(file, "/");
if (charLocation > 0)
{
return file.Substring(0, charLocation);
}
return string.Empty;
}
private static string GetBlobFilename(string file)
{
int charLocation = IndexOfSecond(file, "/");
if (charLocation > 0)
{
return file.Substring(charLocation + 1, file.Length - (charLocation + 1));
}
return string.Empty;
}
private static int IndexOfSecond(string theString, string toFind)
{
int first = theString.IndexOf(toFind);
if (first == -1) return -1;
// Find the "next" occurrence by starting just past the first
return theString.IndexOf(toFind, first + 1);
}
推荐阅读
- hotspot - 创建一个表单以获取信息到热点 mikrotik
- python - 名称错误:python中的图像到文本错误
- curl - 无法满足请求对 GET 请求的响应
- typescript - 从另一种类型创建“可选”类型的快速方法?
- postgresql - GCP 中的 Cloud SQL for PostgreSQL 数据库导出
- ibm-cloud-infrastructure - 如何过滤 REST API SoftLayer_Virtual_Guest::getUpgradeItemPrices 的结果?
- flutter - 如何获取 Flutter / Dart 变量的内存地址?这可能吗?
- python - 如何在字典中的每个条目中插入一个新行?
- python - 如何将初始隐藏状态传递给 lstm 层?
- amazon-s3 - location 参数不是有效的 S3 uri - AWS::Include Location 不接受本地路径但 S3 位置