【问题标题】:WebClient.DownloadDataAsync is returning corrupted dataWebClient.DownloadDataAsync 正在返回损坏的数据
【发布时间】:2019-07-26 10:04:58
【问题描述】:

我正在尝试将数据从应用程序上传和下载到 Web API 的原型。原型将文件 (test.zip) 上传到服务器。服务器将其作为新文件保存到同一文件夹中,然后再次返回 test.zip,客户端保存接收到的文件。上传工作正常,下载运行没有错误。但是,当将接收到的数据写入文件时,文件大小会膨胀约 30%,并在我尝试打开时损坏。

我试图在网上找到有类似问题的人,但没有找到任何结果。我是这个主题的新手,所以不确定自己应该尝试什么。

客户端(控制台应用程序):

static void Main()
{
    ServicePointManager.ServerCertificateValidationCallback += (o, certificate, chain, errors) => true;
    Upload();
    Console.ReadLine();
}

static void Upload()
{
    var webClient = new WebClient();
    var file = File.ReadAllBytes("C:/Users/LPQ/Downloads/Working Folder/test.zip");
    webClient.UploadDataCompleted += (s, e) => Download(webClient);
    webClient.UploadDataAsync(new Uri("localhost/API/APISync/Upload"), file);
}

static void Download(WebClient webClient)
{
    webClient.DownloadDataCompleted += (s, e) =>
    {
        File.WriteAllBytes("C:/Users/LPQ/Downloads/Working Folder/test_SentToClient.zip", e.Result);
        Console.WriteLine("Done");
    };
    webClient.DownloadDataAsync(new Uri("localhost/API/APISync/Download"));
}

服务器

[HttpPost]
[Route("API/APISync/Upload")]
public async Task Upload()
{
    var fileContents = await Request.Content.ReadAsByteArrayAsync();
    File.WriteAllBytes("C:/Users/LPQ/Downloads/Working Folder/test_SentToServer.zip", fileContents);
}

[HttpGet]
[Route("API/APISync/Download")]
public byte[] Download()
{
    return File.ReadAllBytes("C:/Users/LPQ/Downloads/Working Folder/test.zip");
}

text.zip 为 30,837 KB。

上传会生成一个名为 test_SentToServer.zip 的文件,大小为 30,837 KB。

下载后会创建一个名为 test_SentToClient.zip 的文件,但该文件为 41,116 KB,无法打开(损坏)。

显然我希望客户端收到的文件又是 30,837 KB。

【问题讨论】:

  • 附注:如果您查看remarks section of docs,您会发现WebClient 不推荐用于Microsoft
  • 谢谢@vasily.sib 我将尝试使用 HttpClient。注意:我在下载前后仔细检查了文件的字节数组大小。返回前(服务器端):31576982 下载后(客户端):42102646 所以肯定是在下载过程中发生的。
  • 看看你的回复(来自API/APISync/Download)。我敢打赌有一个 HTTP 标头 Content-Type: application/json;,对吗?
  • @vasily.sib 发件人对象中的 Headers 属性为空。具有 Result 属性的 EventArgs 对象只是一个 byte[]。我还有其他方法可以检查吗?
  • @vasily.sib我刚刚尝试对我的 API 使用 HttpClient.GetByteArrayAsync() 方法,结果与 WebClient 完全相同,接收到的文件为 41,116KB!这也向我表明 API 是原因。也许像你建议的标题。我如何检查比接收到的对象的属性更好?将其更改为 GetAsync 并检查响应 -> 内容 -> 包含 application/json 的 Headers 属性

标签: c# asp.net webclient


【解决方案1】:

不要返回原始字节,而是使用FilePathResult

return new FilePathResult(path, "application/octet-stream");

【讨论】:

  • 谢谢,但这导致客户端收到的文件只有 1KB。此外(我可能应该在原始帖子中包含此内容)我使用文件纯粹是作为获取大数据大小的一种方式。要求是保存和接收原始字节。
  • @LPQ 可以在浏览器中使用吗?你修复了内容类型吗? http请求的状态码是什么?
  • 我将内容类型设置为“application/zip”和“application\octet-stream”,结果相同为 1kb。下载需要从 API 转到应用程序。
  • 但它也应该在浏览器中工作。它只是更容易测试。
【解决方案2】:

在拔了一个下午的头发后终于解决了这个问题,这很简单。

在 WebClient.DownloadComplete 事件处理程序中,它被更改为从响应中获取正确的文件数据:

var base64String = System.Text.Encoding.Default.GetString(e.Result).Replace("\"", "");
var fileData = Convert.FromBase64String(base64String);
File.WriteAllBytes("C:/Users/LPQ/Downloads/Working Folder/test_SentToClient.zip", fileData);
Console.WriteLine("Done");

来自服务器的响应是我的 base64 格式数据的字节数组,而不是我的数据的字节数组。所以需要先转成base64字符串,再转成解码后的字节数组。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-26
    • 2018-02-18
    • 1970-01-01
    • 2020-01-01
    相关资源
    最近更新 更多