在商店应用中通过HTTP POST发送字节数组

24

我正试图从Windows Store应用程序通过HTTP POST向服务器发送一些图像和元数据,但在尝试将数据实际包含在POST中时遇到了困难。由于商店应用程序API的更改,无法像在Windows Forms应用程序或类似应用程序中执行此操作。

我遇到了错误。

cannot convert source type byte[] to target type System.Net.Http.httpContent

显然这是由于两种不同的类型不能隐式转换,但这基本上就是我想要做的。我如何将字节数组数据转换为 httpContent 类型,以便包含在以下调用中?

httpClient.PostAsync(Uri uri,HttpContent content);

这是我的完整上传方法:

async private Task UploadPhotos(List<Photo> photoCollection, string recipient, string format)
    {
        PhotoDataGroupDTO photoGroupDTO = PhotoSessionMapper.Map(photoCollection);

        try
        {
            var client = new HttpClient();
            client.MaxResponseContentBufferSize = 256000;
            client.DefaultRequestHeaders.Add("Upload", "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)");

            // POST action_begin
            const string actionBeginUri = "http://localhost:51139/PhotoService.axd?action=Begin";
            HttpResponseMessage response = await client.GetAsync(actionBeginUri);
            response.EnsureSuccessStatusCode();
            string responseBodyAsText = await response.Content.ReadAsStringAsync();
            string id = responseBodyAsText;
            ////

            // POST action_upload
            Uri actionUploadUri = new Uri("http://localhost:51139/PhotoService.axd?action=Upload&brand={0}&id={1}&name={2}.jpg");

            var metaData = new Dictionary<string, string>()
            {
                {"Id", id},
                {"Brand", "M3rror"}, //TODO: Denne tekst skal komme fra en konfigurationsfil.
                {"Format", format},
                {"Recipient", recipient}
            };

            string stringData = "";
            foreach (string key in metaData.Keys)
            {
                string value;
                metaData.TryGetValue(key, out value);
                stringData += key + "=" + value + ",";
            }

            UTF8Encoding encoding = new UTF8Encoding();
            byte[] byteData = encoding.GetBytes(stringData);

            HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, actionUploadUri);

            // send meta data
            // TODO get byte data in as content
            HttpContent metaDataContent = byteData;
            HttpResponseMessage actionUploadResponse = await client.PostAsync(actionUploadUri, metaDataContent);

            actionUploadResponse.EnsureSuccessStatusCode();
            responseBodyAsText = await actionUploadResponse.Content.ReadAsStringAsync();

            // send photos
            // TODO get byte data in as content
            foreach (byte[] imageData in photoGroupDTO.PhotosData)
            {
                HttpContent imageContent = imageData;
                actionUploadResponse = await client.PostAsync(actionUploadUri, imageContent);
                actionUploadResponse.EnsureSuccessStatusCode();
                responseBodyAsText = await actionUploadResponse.Content.ReadAsStringAsync();
            }                
            ////

            // POST action_complete
            const string actionCompleteUri = "http://localhost:51139/PhotoService.axd?action=Complete";
            HttpResponseMessage actionCompleteResponse = await client.GetAsync(actionCompleteUri);
            actionCompleteResponse.EnsureSuccessStatusCode();
            responseBodyAsText = await actionCompleteResponse.Content.ReadAsStringAsync();
            ////
        }

        catch (HttpRequestException e)
        {
        }
        catch (Exception e)
        {
            Debug.WriteLine(e.ToString());
        }
    }

1
二进制数据不需要进行序列化吗?此外,您可能希望将其流式传输而不是一次性上传所有内容。https://dev59.com/BmMk5IYBdhLWcg3wvQcU 可能会有所帮助。 - bytefire
3个回答

65

使用 System.Net.Http.ByteArrayContent 会更加简单明了。例如:

// Converting byte[] into System.Net.Http.HttpContent.
byte[] data = new byte[] { 1, 2, 3, 4, 5};
ByteArrayContent byteContent = new ByteArrayContent(data);
HttpResponseMessage response = await client.PostAsync(uri, byteContent);

如果只使用特定的文本编码,请使用:

// Convert string into System.Net.Http.HttpContent using UTF-8 encoding.
StringContent stringContent = new StringContent(
    "blah blah",
    System.Text.Encoding.UTF8);
HttpResponseMessage response = await client.PostAsync(uri, stringContent);

或者如上所述,对于文本和图像使用multipart/form-data:

// Send binary data and string data in a single request.
MultipartFormDataContent multipartContent = new MultipartFormDataContent();
multipartContent.Add(byteContent);
multipartContent.Add(stringContent);
HttpResponseMessage response = await client.PostAsync(uri, multipartContent);

哪种方法足够快速且安全地处理包含文本和数字组合的数据(约1万条记录的列表- JSON序列化)?是ByteArrayContent还是StringContent。请提供建议。 - Ganesh
我认为上面的变量名应该是"response"而不是"reponse",但我无法编辑它。当我将代码复制/粘贴到现有代码中时,这给我带来了一些问题,如果代码更新为正确的拼写,可能会节省其他人的时间。 - Tim Newton

12
您需要使用HttpContent类型将字节数组封装起来。
如果您正在使用System.Net.Http.HttpClient:
HttpContent metaDataContent = new ByteArrayContent(byteData);
如果您正在使用首选的Windows.Web.Http.HttpClient:
Stream stream = new MemoryStream(byteData);
HttpContent metaDataContent = new HttpStreamContent(stream.AsInputStream());

2
接受ByteArrayContent的服务器端操作模式应该是什么? - Shimmy Weitzhandler
在我的情况下,我正在处理上传到服务器的文件,以便将其发送到另一个服务器的REST API。使用ByteArrayContent无效。 REST服务器只返回状态200的空响应。但是,如果我将上传的数据写入磁盘上的文件,然后使用该文件进行StreamContent,则会起作用。我想知道为什么。 - cdup

1
你要查找的概念被称为序列化。序列化意味着为存储或传输准备数据(这些数据可能是异构且没有预定义的结构)。然后,当您需要再次使用数据时,执行相反的操作,即反序列化,并获取原始数据结构。上面的链接展示了在C#中如何完成这个过程的几种方法。

好提示,谢谢。在其他地方的一个答案中,我正在使用UTF-8解码表单内容。结果发现它是以Base64发送的,所以这就是我需要使用的东西。 - Stuart Aitken

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