使用原始文件名将文件上传到Azure Blob Storage
,并将文件名meta-data
指定给CloudBlob
meta-data
中不允许使用这些字符,但可以接受blob
名称:
š Š ñ Ñ ç Ç ÿ Ÿ ž Ž Ð œ Œ « » éèëêð ÉÈËÊ àâä ÀÁÂÃÄÅ àáâãäå ÙÚÛÜ ùúûüµ òóôõöø ÒÓÔÕÖØ ìíîï ÌÍÎÏ
meta-data
中存储这些字符?我们是否遗漏了一些导致此例外的设置?blob
和meta-data
命名约定,但没有关于数据本身!var dirtyFileName = file.FileName;
var normalizedFileName = file.FileName.CleanOffDiacriticAndNonASCII();
// Blob name accepts almost characters that are acceptable as filenames in Windows
var blob = container.GetBlobReference(dirtyFileName);
//Upload content to the blob, which will create the blob if it does not already exist.
blob.Metadata["FileName"] = normalizedFileName;
blob.Attributes.Properties.ContentType = file.ContentType;
// ERROR: Occurs here!
blob.UploadFromStream(file.InputStream);
blob.SetMetadata();
blob.SetProperties();
文件名中的非法字符只是冰山的一角,仅为此问题而放大!更大的情况是我们使用Lucene.net
索引这些文件,因此需要将大量meta-data
存储在blob
上。 请不要建议将它们全部存储在一个数据库中,只是不要!到目前为止,我们很幸运只遇到一个带有变音字符的文件!
所以,目前我们正努力避免在meta-data
中保存文件名作为解决方法!
答案 0 :(得分:13)
来自azure-sdk-for-net
team on GitHub的确认只有ASCII
个字符作为blob meta-data
中的数据有效。
joeg评论说:
blob元数据中支持的字符必须是ASCII字符。要解决 你可以转义字符串(百分比编码),base64编码等。
作为一种解决方法,要么:
答案 1 :(得分:6)
除非得到实际解决问题的答案,否则此解决方法可解决上述问题!
为了实现这一点,我使用以下方法的组合:
但这并不理想,因为我们正在丢失数据!
/// <summary>
/// Converts all Diacritic characters in a string to their ASCII equivalent
/// Courtesy: http://stackoverflow.com/a/13154805/476786
/// A quick explanation:
/// * Normalizing to form D splits charactes like è to an e and a nonspacing `
/// * From this, the nospacing characters are removed
/// * The result is normalized back to form C (I'm not sure if this is neccesary)
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public static string ConvertDiacriticToASCII(this string value)
{
if (value == null) return null;
var chars =
value.Normalize(NormalizationForm.FormD)
.ToCharArray()
.Select(c => new {c, uc = CharUnicodeInfo.GetUnicodeCategory(c)})
.Where(@t => @t.uc != UnicodeCategory.NonSpacingMark)
.Select(@t => @t.c);
var cleanStr = new string(chars.ToArray()).Normalize(NormalizationForm.FormC);
return cleanStr;
}
/// <summary>
/// Removes all non-ASCII characters from the string
/// Courtesy: http://stackoverflow.com/a/135473/476786
/// Uses the .NET ASCII encoding to convert a string.
/// UTF8 is used during the conversion because it can represent any of the original characters.
/// It uses an EncoderReplacementFallback to to convert any non-ASCII character to an empty string.
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public static string RemoveNonASCII(this string value)
{
string cleanStr =
Encoding.ASCII
.GetString(
Encoding.Convert(Encoding.UTF8,
Encoding.GetEncoding(Encoding.ASCII.EncodingName,
new EncoderReplacementFallback(string.Empty),
new DecoderExceptionFallback()
),
Encoding.UTF8.GetBytes(value)
)
);
return cleanStr;
}
我真的希望得到答案,因为解决方法显然不理想,而且为什么这是不可能的也没有意义!
答案 2 :(得分:2)
为了扩展bPratik的答案,我们发现Base64编码元数据运行良好。我们使用这种扩展方法来进行编码和解码:
public static class Base64Extensions
{
public static string ToBase64(this string input)
{
var bytes = Encoding.UTF8.GetBytes(input);
return Convert.ToBase64String(bytes);
}
public static string FromBase64(this string input)
{
var bytes = Convert.FromBase64String(input);
return Encoding.UTF8.GetString(bytes);
}
}
然后在设置blob元数据时:
blobReference.Metadata["Filename"] = filename.ToBase64();
并在检索时:
var filename = blobReference.Metadata["Filename"].FromBase64();
对于搜索,您必须在将文件名呈现给索引器之前对其进行解码,或者使用blob的实际文件名,假设您仍然使用原始文件名。
答案 3 :(得分:0)
如果上面的列表是详尽无遗的,那么应该可以将元数据编码为HTML,然后在需要时对其进行解码:
var htmlEncodedValue = System.Web.HttpUtility.HtmlEncode(value)
var originalValue = System.Web.HttpUtility.HtmlDecode(value)