本文介绍了如何使用 C# HttpClient PostAsync 显示上传进度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 Xamarin PCL 创建一个适用于 Android 和 iOS 的文件上传应用程序,我已经设法实现文件上传和某种进度条,但它无法正常工作.

A am creating a file upload app for Android and iOS using Xamarin PCL and i have managed to implement file upload and some sort of progress bar, but it is not working properly.

我在堆栈溢出中看到了一些显示下载进度的答案,但我想通知我的用户关于上传进度并且没有找到任何解决方案.

I saw some answers on stack overflow for displaying download progress, but i want to notify my users about upload progress and did not find any solution.

这是我的代码:

public static async Task<string> PostFileAsync (Stream filestream, string filename, int filesize) {
        var progress = new System.Net.Http.Handlers.ProgressMessageHandler ();

        //Progress tracking
        progress.HttpSendProgress += (object sender, System.Net.Http.Handlers.HttpProgressEventArgs e) => {
            int progressPercentage = (int)(e.BytesTransferred*100/filesize);
            //Raise an event that is used to update the UI
            UploadProgressMade(sender, new System.Net.Http.Handlers.HttpProgressEventArgs(progressPercentage, null, e.BytesTransferred, null));
        };

        using (var client = HttpClientFactory.Create(progress)) {
            using (var content = new MultipartFormDataContent ("------" + DateTime.Now.Ticks.ToString ("x"))) {
                content.Add (new StreamContent (filestream), "Filedata", filename);
                using (var message = await client.PostAsync ("http://MyUrl.example", content)) {
                    var result = await message.Content.ReadAsStringAsync ();
                    System.Diagnostics.Debug.WriteLine ("Upload done");
                    return result;
                }
            }
        }
    }

显示某种进度,但当进度达到 100% 时,文件尚未上传.在我收到最后一条进度消息后的一段时间内,也会打印消息上传完成".

Some sort of progress is displayed, but when the progress reaches 100%, the file is not uploaded yet. Message "Upload done" is also printed some time after i have received the last progress message.

也许进度显示的是从设备发出的字节数,而不是已经上传的字节数,所以当它说是 100% 时,所有的字节数都刚刚发出,但服务器还没有收到?

Maybe the progress is displaying bytes sent out of the device and not already uploaded bytes, so when it says, that it is 100%, all of the bytes are just sent out but not yet received by the server?

尝试了这个解决方案:https://forums.xamarin.com/discussion/56716/plans-to-add-webclient-to-pcl 并且效果更好.

Tried this solution: https://forums.xamarin.com/discussion/56716/plans-to-add-webclient-to-pcl and it works a bit better.

推荐答案

试试这样:

我遇到了同样的问题.我通过实现自定义 HttpContent 修复了它.我使用这个对象来跟踪上传进度的百分比,你可以添加一个事件并收听它.您应该自定义 SerializeToStreamAsync 方法.

I faced same issue. I fixed it by implementing custom HttpContent. I use this object to track percentage of upload progress, you can add an event to and listen it. You should customize SerializeToStreamAsync method.

internal class ProgressableStreamContent : HttpContent
{
    private const int defaultBufferSize = 4096;

    private Stream content;
    private int bufferSize;
    private bool contentConsumed;
    private Download downloader;

    public ProgressableStreamContent(Stream content, Download downloader) : this(content, defaultBufferSize, downloader) {}

    public ProgressableStreamContent(Stream content, int bufferSize, Download downloader)
    {
        if(content == null)
        {
            throw new ArgumentNullException("content");
        }
        if(bufferSize <= 0)
        {
            throw new ArgumentOutOfRangeException("bufferSize");
        }

        this.content = content;
        this.bufferSize = bufferSize;
        this.downloader = downloader;
    }

    protected override Task SerializeToStreamAsync(Stream stream, TransportContext context)
    {
        Contract.Assert(stream != null);

        PrepareContent();

        return Task.Run(() =>
        {
            var buffer = new Byte[this.bufferSize];
            var size = content.Length;
            var uploaded = 0;

            downloader.ChangeState(DownloadState.PendingUpload);

            using(content) while(true)
            {
                var length = content.Read(buffer, 0, buffer.Length);
                if(length <= 0) break;

                downloader.Uploaded = uploaded += length;

                stream.Write(buffer, 0, length);

                downloader.ChangeState(DownloadState.Uploading);
            }

            downloader.ChangeState(DownloadState.PendingResponse);
        });
    }

    protected override bool TryComputeLength(out long length)
    {
        length = content.Length;
        return true;
    }

    protected override void Dispose(bool disposing)
    {
        if(disposing)
        {
            content.Dispose();
        }
        base.Dispose(disposing);
    }


    private void PrepareContent()
    {
        if(contentConsumed)
        {
            // If the content needs to be written to a target stream a 2nd time, then the stream must support
            // seeking (e.g. a FileStream), otherwise the stream can't be copied a second time to a target
            // stream (e.g. a NetworkStream).
            if(content.CanSeek)
            {
                content.Position = 0;
            }
            else
            {
                throw new InvalidOperationException("SR.net_http_content_stream_already_read");
            }
        }

        contentConsumed = true;
    }
}

参考:

这篇关于如何使用 C# HttpClient PostAsync 显示上传进度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-04 05:52
查看更多