使用ServiceStack的PostFileWithRequest方法上传文件时显示进度

时间:2012-12-06 21:32:46

标签: servicestack

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

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

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

1 个答案:

答案 0 :(得分: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. 
        }
    }
}