Windows Store App HttpClient进度

时间:2016-04-05 14:38:10

标签: http windows-10-universal

我需要在app中提供任意文件的下载进度。 我以为我可以使用HttpClient.GetInputStreamAsync进度,但它并不精细。进度通知非常罕见。以下代码:

$ gradle -v --stacktrace

FAILURE: Build failed with an exception.

* What went wrong:
Failed to load native library 'native-platform.dll' for Windows 7 amd64.

* Try:
Run with --info or --debug option to get more log output.

* Exception is:
net.rubygrapefruit.platform.NativeException: Failed to load native library 'nati                                        ve-platform.dll' for Windows 7 amd64.
        at net.rubygrapefruit.platform.internal.NativeLibraryLoader.load(NativeL                                        ibraryLoader.java:49)
        at net.rubygrapefruit.platform.Native.init(Native.java:55)
        at org.gradle.internal.nativeintegration.services.NativeServices.initial                                        ize(NativeServices.java:74)
        at org.gradle.internal.nativeintegration.services.NativeServices.initial                                        ize(NativeServices.java:60)
        at org.gradle.launcher.cli.CommandLineActionFactory$WithLogging.execute(                                        CommandLineActionFactory.java:203)
        at org.gradle.launcher.cli.CommandLineActionFactory$WithLogging.execute(                                        CommandLineActionFactory.java:169)
        at org.gradle.launcher.cli.ExceptionReportingAction.execute(ExceptionRep                                        ortingAction.java:33)
        at org.gradle.launcher.cli.ExceptionReportingAction.execute(ExceptionRep                                        ortingAction.java:22)
        at org.gradle.launcher.Main.doAction(Main.java:33)
        at org.gradle.launcher.bootstrap.EntryPoint.run(EntryPoint.java:45)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.                                        java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces                                        sorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:497)
        at org.gradle.launcher.bootstrap.ProcessBootstrap.runNoExit(ProcessBoots                                        trap.java:54)
        at org.gradle.launcher.bootstrap.ProcessBootstrap.run(ProcessBootstrap.j                                        ava:35)
        at org.gradle.launcher.GradleMain.main(GradleMain.java:23)
Caused by: java.io.IOException: The system cannot find the path specified
        at java.io.WinNTFileSystem.createFileExclusively(Native Method)
        at java.io.File.createNewFile(File.java:1012)
        at net.rubygrapefruit.platform.internal.NativeLibraryLocator.find(Native                                        LibraryLocator.java:39)
        at net.rubygrapefruit.platform.internal.NativeLibraryLoader.load(NativeL                                        ibraryLoader.java:41)
        ... 16 more

输出:

var httpClient = new HttpClient();
var path = new Uri(@"http://<path>");

using (var inputStream = (await httpClient.GetInputStreamAsync(path).AsTask(new MyProgress())).AsStreamForRead())
{
    var outputFile = await ApplicationData.Current.TemporaryFolder.CreateFileAsync("output.mov", CreationCollisionOption.ReplaceExisting);

    using (var outputStream = (await outputFile.OpenAsync(FileAccessMode.ReadWrite)).AsStreamForWrite())
    {
        await inputStream.CopyToAsync(outputStream);

        await outputStream.FlushAsync();
    }
}

Debug.WriteLine("done");


private class MyProgress : IProgress<HttpProgress>
{
    public void Report(HttpProgress value)
    {
        Debug.WriteLine("HTTP {0} progress {1}/{2}", value.Stage, value.BytesReceived, value.TotalBytesToReceive);
    }
}

因此,在某些时候,接收的总字节数是已知的,但在文件下载期间没有报告进度。

1 个答案:

答案 0 :(得分:1)

我最终得到了如下解决方案:

var httpClient = new HttpClient();

var path = new Uri(@"http://<path>");

var progressHelper = new ProgressHelper();

using (var inputStream = (await httpClient.GetInputStreamAsync(path).AsTask(progressHelper)).AsStreamForRead())
{
    var outputFile = await ApplicationData.Current.TemporaryFolder.CreateFileAsync("output.mov", CreationCollisionOption.ReplaceExisting);

    using (var outputStream = (await outputFile.OpenAsync(FileAccessMode.ReadWrite)).AsStreamForWrite())
    {
        var buffer = new byte[1024 * 1024];
        int read;

        while ((read = await inputStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
        {
            progressHelper.BytesReceived += (ulong)read;

            await outputStream.WriteAsync(buffer, 0, read);
        }

        await outputStream.FlushAsync();
    }
}

Debug.WriteLine("done");


private class ProgressHelper : IProgress<HttpProgress>
{
    private ulong _bytesReceived = 0;
    private ulong? _totalBytesToReceive = null;

    public void Report(HttpProgress value)
    {
        Debug.WriteLine("HTTP {0} progress {1}/{2}", value.Stage, value.BytesReceived, value.TotalBytesToReceive);

        TotalBytesToReceive = value.TotalBytesToReceive;                
    }

    public ulong? TotalBytesToReceive
    {
        get
        {
            return _totalBytesToReceive;
        }
        set
        {
            if (_totalBytesToReceive == value)
                return;

            _totalBytesToReceive = value;
            UpdateProgress();
        }
    }

    public ulong BytesReceived
    {
        get
        {
            return _bytesReceived;
        }
        set
        {
            if (_bytesReceived == value)
                return;

             _bytesReceived = value;
            UpdateProgress();
        }
    }

    public int? Progress
    {
        get
        {
            if (_totalBytesToReceive.HasValue)
            {
                return (int)Math.Round((100.0 * _bytesReceived) / _totalBytesToReceive.Value);
            }

            return null;
        }
    }

    private void UpdateProgress()
    {
        Debug.WriteLine("Progress: {0}", Progress);
    }
}
相关问题