CloudBlockBlob DownloadTextAsync 行为差异

CloudBlockBlob DownloadTextAsync Behavior Difference

我正在使用带有事件网格触发器和 CloudBlockBlob 作为输入绑定的 azure 函数。使用 DownloadTextAsync(AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext)

从 CloudBlockBob 下载内容

如果上面下载的文件是使用 XmlDocument 生成的,DownloadTextAsync returns 乱码。但是,如果文件是使用 FileStream 生成的,则可以正常工作。 PFB生成文件的实现-

  1. 使用 XmlDocument
var stringwriter = new System.IO.StringWriter();
var serializer = new XmlSerializer(typeof(List<ContractName>), new XmlRootAttribute("RootAttributeName"));
serializer.Serialize(stringwriter, contractData);
var xmlString = stringwriter.ToString();

XmlDocument doc = new XmlDocument();
doc.LoadXml(xmlString);
doc.PreserveWhitespace = true;
doc.Save(fileName);
  1. 使用文件流
var serializer = new XmlSerializer(typeof(List<ContractName>), new XmlRootAttribute("RootAttributeName"));

var file = new FileStream(fileName, FileMode.OpenOrCreate);           
serializer.Serialize(file, contractData);
file.Close();

用于下载内容的代码-

  1. 使用 DownloadTextAsync
private static async System.Threading.Tasks.Task<string> DownloadContentAsync_DownloadTextAsync(string storageAccountConnectionString, string containerName, string blobName)
        {
            CloudBlobContainer container = GetContainer(storageAccountConnectionString, containerName);
            ICloudBlob blob = await container.GetBlobReferenceFromServerAsync(blobName);

            // Download the blob content
            string xmlBlobContent =
                await (blob as CloudBlockBlob).DownloadTextAsync(
                    null,
                    new BlobRequestOptions { LocationMode = LocationMode.PrimaryThenSecondary },
                    new OperationContext());

            return xmlBlobContent;
        }
  1. 使用 DownloadToStreamAsync
private static async System.Threading.Tasks.Task<string> DownloadContentAsync_DownloadToStreamAsync(string storageAccountConnectionString, string containerName, string blobName)
        {
            CloudBlobContainer container = GetContainer(storageAccountConnectionString, containerName);
            ICloudBlob blob = await container.GetBlobReferenceFromServerAsync(blobName);

            // Download the blob content
            MemoryStream resultStream = new MemoryStream();
            await (blob as CloudBlockBlob).DownloadToStreamAsync(
                resultStream,
                null,
                new BlobRequestOptions { LocationMode = LocationMode.PrimaryThenSecondary },
                new OperationContext());
            string xmlBlobContent = System.Text.Encoding.UTF8.GetString(resultStream.ToArray());

            return xmlBlobContent;
        }

为什么 DownloadTextAsync 的响应不同。

更新 0713:

想通了。根本原因是当您使用 XmlDocument 生成 xml 文件时,编码是 utf-16。但是对于 FileStream,它会生成编码为 utf-8.

的 xml 文件

所以,解决方案是,当使用XmlDocument时,我们可以将编码指定为utf-8FileStream无需更改代码)。示例代码如下:

生成 xml 文件使用 XmlDocument:

               //2. Using XMLDoc
                serializer.Serialize(stringwriter, contractData);
                var xmlString = stringwriter.ToString();
                XmlDocument doc = new XmlDocument();

                doc.LoadXml(xmlString);
                doc.PreserveWhitespace = true;
                string fileName = String.Format(@"C:\TestBlobDownloadContent\UsingXMLDoc" + count + ".xml");

                //encoding as utf-8
                using (TextWriter sw = new StreamWriter(fileName, false, Encoding.UTF8))
                {
                    doc.Save(sw);
                }

通过DownloadTextAsync()方法从blob存储中读取xml文件时,无需指定编码选项,如下所示:

        // Download the blob content
        string xmlBlobContent =
            await (blob as CloudBlockBlob).DownloadTextAsync(
                null,
                new BlobRequestOptions { LocationMode = LocationMode.PrimaryThenSecondary },
                new OperationContext());

原回答:

这是由于 encode/decode 问题造成的。

解决方案:

DownloadTextAsync()方法中,添加参数System.Text.Encoding.Unicode。如下所示:

 string xmlBlobContent =
             await (blob as CloudBlockBlob).DownloadTextAsync(
                            System.Text.Encoding.Unicode,
                            null,
                            new BlobRequestOptions { LocationMode = LocationMode.PrimaryThenSecondary },
                            new OperationContext());

测试结果: