在Windows Store应用中使用httpclient获取UTF-8响应

21

我正在开发一个Windows Store应用,但是在从API获取UTF-8响应方面遇到了困难。

以下是代码:

using (HttpClient client = new HttpClient())
{
    Uri url = new Uri(BaseUrl + "/me/lists");

    HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, url);
    request.Headers.Add("Accept", "application/json");
    HttpResponseMessage response = await client.SendRequestAsync(request);
    response.EnsureSuccessStatusCode();

    string responseString = await response.Content.ReadAsStringAsync();

    response.Dispose();
}

reponseString总是包含奇怪的字符,这些字符应该是重音符号,比如é,我尝试使用流(stream)来解决问题,但我在一些示例中发现的API在Windows RT中不存在。

编辑:改进了代码,仍然存在相同的问题。


你确定你所调用的API能够正确处理非ASCII文本吗?(从你的代码中很难猜测你在调用什么) - Alexei Levenkov
你描述的问题非常不清楚。你期望得到一个UTF-8响应吗?服务器是否发送了一个UTF-8响应?你可以使用Fiddler直接访问Web服务以查看它返回了什么。 - WiredPrairie
响应的Content-Type头是否设置为正确的值?您尝试过_client.GetStringAsync(url)方法吗? - cremor
@WiredPrairie 我不知道如何使用Fiddler进行HTTPS请求。但是在Chrome REST控制台中,我看到了一个UTF-8响应。 - Sam Debruyn
@cremor 尝试过了,同样的问题 :/ - Sam Debruyn
显示剩余2条评论
7个回答

36

你可以像@Kiewic指出的那样,使用response.Content.ReadAsBufferAsync(),而不是直接使用response.Content.ReadAsStringAsync()

var buffer = await response.Content.ReadAsBufferAsync();
var byteArray = buffer.ToArray();
var responseString = Encoding.UTF8.GetString(byteArray, 0, byteArray.Length);

这在我的情况下有效,我猜使用UTF8应该解决大部分问题。现在去想为什么没有办法使用ReadAsStringAsync来做到这一点 :)


这是一个笔误吗?方法名好像只是重复了:“Instead of using response.Content.ReadAsStringAsync() directly you could use response.Content.ReadAsStringAsync()”。 - superjos
@superjos 你说得对,那里有个打字错误,方法应该是ReadAsBufferAsync。我已经修正了它。 - Camilo Martinez
我遇到了这个问题,但是这并不能解决我的问题。我的代码在.NET Core中运行良好,但在UWP中出现了乱码字符。 - Christian Findlay
7
ReadAsBufferAsync不存在,也许是ReadAsByteArrayAsync? - syonip

8
我这样解决了它:
using (HttpClient client = new HttpClient())
    {
        using (HttpResponseMessage response = await client.GetAsync(url))
            {
                var byteArray = await response.Content.ReadAsByteArrayAsync();
                var result = Encoding.UTF8.GetString(byteArray, 0, byteArray.Length);
                return result;
            }
    }

4
也许问题在于响应已被压缩。如果内容类型为gzip,则需要将响应解压缩为字符串。一些服务器这样做是为了节省带宽,通常情况下这是可以接受的。在.NET Core和可能是.NET Framework中,这将自动解压缩响应。但在UWP中却无法正常工作。对我来说,这似乎是UWP中一个明显的错误。
string responseString = await response.Content.ReadAsStringAsync();

这个线程提供了一个清晰的例子来展示如何解压响应: 使用C#压缩/解压字符串

2
这对我解决了问题。在尝试解压响应之前,为确保安全,我通过注释掉 HttpClient.DefaultRequestHeaders.Add("*Accept-Encoding*", "gzip, deflate, br"); 来禁用了“Accept-Encoding”头,并且此后它可以正常工作。 - Anthony Walsh
难以想象在UWP平台上这个问题仍然存在 - Christian Findlay

3

我喜欢El Marchewko的方法,使用扩展程序,但是这段代码对我不起作用。以下代码可以正常运行:

using System.IO;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;

namespace WannaSport.Data.Integration
{
    public static class HttpContentExtension
    {
        public static async Task<string> ReadAsStringUTF8Async(this HttpContent content)
        {
            return await content.ReadAsStringAsync(Encoding.UTF8);
        }

        public static async Task<string> ReadAsStringAsync(this HttpContent content, Encoding encoding)
        {
            using (var reader = new StreamReader((await content.ReadAsStreamAsync()), encoding))
            {
                return reader.ReadToEnd();
            }
        }
    }
}

我在UWP中遇到了相同的问题。我的代码在.NET Core中运行良好,但在UWP中出现了完全混乱的字符。我尝试了这个确切的代码,但它没有起作用。 - Christian Findlay

1

HttpClient 不太灵活。

你可以使用 HttpWebRequest 代替,并使用 HttpWebResponse.GetResponseStream() 获取响应的原始字节。


2
Stream stream = await response.Content.ReadAsStreamAsync() 是什么意思? - kiewic

0

使用扩展的方法:

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using Windows.Web.Http;

    namespace yourfancyNamespace
    {
        public static class IHttpContentExtension
        {
            public static async Task<string> ReadAsStringUTF8Async(this IHttpContent content)
            {
                return await content.ReadAsStringAsync(Encoding.UTF8);
            }
            public static async Task<string> ReadAsStringAsync(this IHttpContent content, Encoding encoding)
            {
                using (TextReader reader = new StreamReader((await content.ReadAsInputStreamAsync()).AsStreamForRead(), encoding))
                {
                    return reader.ReadToEnd();
                }
            }
        }
    }

0

暂时不能评论,所以我只能在这里分享我的想法。

您可以尝试使用如@cremor所建议的_client.GetStringAsync(url),并使用_client.DefaultRequestHeaders属性设置身份验证标头。 或者,您还可以尝试在response.Content对象上使用ReadAsByteArrayAsync方法,并使用System.Text.Encoding将该字节数组解码为UTF-8字符串。


ReadAsByteArrayAsync 在 WinRT 中不可用。 - Sam Debruyn
@SamuelDebruyn response.Content.ReadAsByteArrayAsync() 在WinRT中得到支持。 - kiewic
@Kiewic 当我开始输入 response.Content.Read... 时,我只得到了三个选项:ReadAsBufferAsyncReadAsInputStreamAsyncReadAsStringAsync - Sam Debruyn
2
哦,你正在使用Wondows.Web.Http.HttpClient,那么ReadAsBuffer应该可以工作。你可以将缓冲区转换为字节数组。 - kiewic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接