2

目前,我正在尝试使用便携式库中的 Web 服务从服务器上传文件。对于每个文件,我都这样做:

WebRequest request = WebRequest.Create("http://localhost:49364/" + url);

 request.BeginGetResponse((aResult) =>
 {
      var retour = aResult.AsyncState as WebRequest;
      WebResponse reponse = retour.EndGetResponse(aResult);
      callback(reponse);
 }, request);

在我的回调方法中,我这样做:

byte[] bytes;
string currentFileName = fileName;
string categorie = currentFileName.Split('/').ElementAt(0);
string dir = currentFileName.Split('/').ElementAt(1);

using (var reader = new BinaryReader(reponse2.GetResponseStream()))
{
    bytes = new byte[reponse2.ContentLength];
    reader.Read(bytes, 0, (int)reponse2.ContentLength);
}
fileService.EnsureFolderExists(categorie);
fileService.EnsureFolderExists(fileService.PathCombine(categorie, dir));
fileService.WriteFile(currentFileName, bytes);

我将整个文件作为字节数组获取。但是,使用 winRT,写入文件会很快停止,并且我的本地文件不完整。如果我尝试只上传一个文件,写入也会停止。但是,如果我尝试使用 Silverlight(我将 MvvmCross 扩展到 Silverlight),则编写完成。我还没有测试过 MonoDroid 和 MonoTouch。

所以,我的问题是:为什么写作停止了?

4

2 回答 2

2

我查看了MvxBlockingWinRTFileStoreService.cs中 WriteFile 的代码,但看不到任何明显的错误。

为了测试这一点,我刚刚使用https://gist.github.com/4016898编写了一个快速的独立 WinRT 测试应用程序。

这完美地保存了 37kB 的 Bing 主页文件。它也适用于您的服务器吗?

在这个测试之后,我的猜测是您的网络传输代码中可能存在一些错误 - 甚至可能在 localhost 服务中。但是,该错误仍然可能存在于 StorageFile 保存中。

一些问题:

  • 您可以添加额外的跟踪来找出下载过程中每个阶段报告的数据缓冲区长度吗?

  • 您能否调整上面的简单测试工具以显示相同的结果?


一种可能的候选人是:

您使用 ContentLength 作为流长度?你确定这是正确的长度吗?

例如,如果您启用了 GZip 压缩,那么 ContentLength 将为您提供传输的压缩数据的长度,而不是数据本身的长度 - 请参阅使用 http 压缩时的 content-length

我想得越多,这对我来说就越有意义——Silverlight 将使用浏览器堆栈,与 WinRT 堆栈相比,该堆栈将具有不同的 HTTP 接受标头。


一些好消息是 async/await 很快就会出现在 MonoTouch 和 MonoDroid 中——当它们出现时,我将尝试使文件 API 都可以作为 async 和 await 使用。

于 2012-11-05T12:12:40.220 回答
1

斯图尔特,

首先,感谢您的回答!

我尝试了您的示例并适应了我的情况(通过网络服务从服务器上传文件),起初一切正常。所有文件均已正确上传。但是当我添加要上传的图像时,我遇到了同样的问题。图像文件和文本文件不完整。

但是查看您示例的代码,我找到了解决方案,以为我不太明白问题出在哪里。

对于写作作品,我替换了这个(在我的回调方法中):

...

using (var reader = new BinaryReader(reponse2.GetResponseStream()))
{
    bytes = new byte[reponse2.ContentLength];
    reader.Read(bytes, 0, (int)reponse2.ContentLength);
}
...
fileService.WriteFile(currentFileName, bytes);

这样 :

...

var mem = new MemoryStream();
using (var stream = reponse2.GetResponseStream())
{
        stream.CopyTo(mem);
}
mem.Seek(0L, SeekOrigin.Begin);
...
fileService.WriteFile(currentFileName, mem.ToArray());

我不知道为什么,但它有效!(如果你知道为什么会这样,我很感兴趣)

所以,谢谢你的帮助!

于 2012-11-05T15:28:05.927 回答