WebClient.DownloadDataAsync 正在返回损坏的数据
WebClient.DownloadDataAsync is returning corrupted data
我正在尝试制作从应用程序到 Web 的数据上传和下载原型 API。原型将文件 (test.zip) 上传到服务器。服务器将其作为新文件保存到同一文件夹,然后再次 returns 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。
不要 return 原始字节,使用 FilePathResult 代替
return new FilePathResult(path, "application/octet-stream");
拔了一个下午的头发终于解决了,原来是这么简单的事情。
在 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字符串,再转成解码后的字节数组。
我正在尝试制作从应用程序到 Web 的数据上传和下载原型 API。原型将文件 (test.zip) 上传到服务器。服务器将其作为新文件保存到同一文件夹,然后再次 returns 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。
不要 return 原始字节,使用 FilePathResult 代替
return new FilePathResult(path, "application/octet-stream");
拔了一个下午的头发终于解决了,原来是这么简单的事情。
在 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字符串,再转成解码后的字节数组。