2

我正在开发一个使用 ServiceStack、Mono For Android 和 MonoTouch 的 Android 和 iPhone 移动应用程序。该应用程序的一部分允许用户将文件上传到我们的服务器,我目前正在通过 'JsonServiceClient.PostFileWithRequest(string relativeOrAbsoluteUrl, Stream fileToUpload, string fileName, object request)' 方法执行此操作。这工作正常,但是我想显示一个进度条,指示发送的数据。

对于我的第一次尝试,我创建了一个包装 Stream 的类,并在从流中读取数据时定期引发 ProgressChanged 事件。不幸的是,这并不能很好地工作,因为似乎所有数据都是在任何发送对象之前从流中读取的(至少对于我测试过的高达 90Mb 的文件)。效果是进度条快速运行到 100%,然后在数据实际传输到服务器时处于 100%。最终 PostFileWithRequest() 调用完成,文件传输成功,但进度条行为不太理想。

有没有人对我如何获得更准确地代表文件上传进度的进度更新有任何建议?

4

1 回答 1

0

我想出的解决这个问题的解决方案是将源流分成块并多次调用“PostFileWithRequest”。我在通话后更新进度条。使用这种方法很容易实现取消和重新启动上传,但我确信这不会特别有效。

无论如何,在伪代码中,我的解决方案看起来像这样:

using (var client = new JsonServiceClient(WebServiceAddress))
{
    var src = GetStreamForFileToSend();
    long totalBytes = src.CanSeek ? src.Length : 0;
    long byteOffset = 0;

    byte[] Chunk = new byte[Constants.UploadChunkSize];
    for (int read; (read = src.Read(Chunk, 0, Chunk.Length)) != 0;)
    {
        // Progress update
        UploadProgress(byteOffset, totalBytes);

        using (var mem = new MemoryStream(Chunk, 0, read))
        {
            // The request contains a guid so the web service can concatenate chunks
            // from the same client
            var request = new UploadFileData(MyUniqueClientGuid, byteOffset, totalBytes);

            // Send the chunk
            UploadFileDataResponse response = client.PostFileWithRequest<UploadFileData>(
                UploadFileData.Route, mem, filename, request);

            // Cancelling supported easily...
            if (response.Cancelled)
                break;

            byteOffset += read;

            // Can also use 'src.Seek()' and send only the remainder of the file if the
            // response contains info about how much of the file is already uploaded. 
        }
    }
}
于 2012-12-11T02:51:41.127 回答