4

I'm sorry if this question has been answered before, but none of the answers helped me. I have an event for my WebView:

private async void MainWebView_UnviewableContentIdentified(WebView sender, WebViewUnviewableContentIdentifiedEventArgs args)
{
    await downloadFromUri(args.Uri).ConfigureAwait(false);
}

My downloadFromUri method will attempt to download a file and store it in the downloads folder and finally it will open the file:

    static async Task downloadFromUri(Uri uri)
    {
        var url = uri;

        HttpClient client = new HttpClient();

        client.DefaultRequestHeaders.TryAppendWithoutValidation(
          "Authorization Bearer",
              " MYTOKEN"
              );

        Debug.WriteLine("Attempting GET request");

        var response = await client.GetAsync(url);

        Debug.WriteLine("Got response.. checking " + response.StatusCode);


        if (response.IsSuccessStatusCode)
        {
            Debug.WriteLine("Okay, we've got a response");
            var responseFileName = response.Content.Headers.ContentDisposition.FileName;

            Debug.WriteLine("Filename: " + responseFileName);

            var ManualFile = await DownloadsFolder.CreateFileAsync(responseFileName, CreationCollisionOption.GenerateUniqueName);

            Debug.WriteLine("Creating buffer: ");
            var buffer = await client.GetBufferAsync(url);

            Debug.WriteLine("Writing buffer.");
            await Windows.Storage.FileIO.WriteBufferAsync(ManualFile, buffer);

            Debug.WriteLine("Done, opening");

            var openOptions = new Windows.System.LauncherOptions();
            openOptions.DisplayApplicationPicker = true;

            var openFile = await Windows.System.Launcher.LaunchFileAsync(ManualFile, openOptions);
        }
        else
        {
            Debug.WriteLine(response.StatusCode.ToString());
        }     
    }

The thing is, this code seems to work fine on small PDF or zip files. But when it comes to PDF files that are > 10mb, the application just hangs at the following line:

var response = await client.GetAsync(url);

What can I do to make this work? Thanks a lot in advance!

Note: I'm using the Windows.Web.Http.HttpClient and not the System.Net.Http.HttpClient.

Edit: I've tried to skip the client.GetAsync(url)and run the var buffer = await client.GetBufferAsync(url); directly. This also returns in a hang.

Koeno
  • 1,493
  • 2
  • 16
  • 30
  • Did you update the maxRequestLength property in config ? Have you alse considered changing the GetAsync to ReadAsStreamAsync and write the Stream to a file? The file would be not downloaded in-memory, but directly saved into a file, I think. – Miłosz Wieczorek Apr 04 '17 at 11:40

2 Answers2

3

Maybe for larger files, it is better to use the

Windows.Networking.BackgroundTransfer

namespace, like the BackgroundDownloader?

Luca Lindholm
  • 813
  • 1
  • 9
  • 23
  • As far as I know you can't find the file name with the background downloader. This is mandatory. Or am I missing something? – Koeno Apr 10 '17 at 08:01
2

Please change your code to-

var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false));

Also refer this- HttpClient.GetAsync(...) never returns when using await/async

Or, you can also using TPL to execute your long running function in a Task which will be managed the OS thread pool.

var result = Task.Run(() => downloadFromUri(uri)).Result;
Community
  • 1
  • 1
Souvik Ghosh
  • 4,456
  • 13
  • 56
  • 78
  • The method .ConfigureAwait() is not available for the Windows.Web.Http.HttpClient.GetAsync method. As I said, I'm using the Windows.Web.Http.HttpClient. I will try your second suggestion! – Koeno Mar 29 '17 at 09:03
  • For your second suggestion I'm getting this exception: (Exception from HRESULT: 0x8001010E (RPC_E_WRONG_THREAD))' – Koeno Mar 29 '17 at 09:27
  • 1
    Oh I see. Can you use 'System.Net.Http.HttpClient' or is there a particular reason for doing that. If you still want to go with current implementation, you can use a cancellation token and timeout. It is better to set a timeout to avoid waiting indefinitely. Refer- http://stackoverflow.com/questions/19535004/windows-web-http-httpclient-timeout-option – Souvik Ghosh Mar 29 '17 at 11:57
  • I've tried your cancellation token with 60 seconds. Then after 60 seconds the task is canceled (the TaskCanceledException is thrown). It works fine with for example 2mb PDF files, but with 10mb+ PDF files it just doesn't. Im using this PDF for testing: https://www.iso.org/files/live/sites/isoorg/files/archive/pdf/en/annual_report_2009.pdf – Koeno Mar 29 '17 at 12:38
  • Then it looks like your request for 10+ MB files takes longer than 60 seconds? Or may be the source URL server disconnects you. You may increase the timeout though. But I really recommend you to combine both the first approach along with the cancellation token. HttpCompletionOption does cause a significant difference. – Souvik Ghosh Mar 29 '17 at 13:39
  • I did use your suggestion: var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead).AsTask(source.Token); is the code I'm currently using – Koeno Mar 29 '17 at 13:44
  • 2
    If your'e going to download large files then httpclient wont suit. use background downloader. https://github.com/Kumara-Krishnan/Windows-universal-samples/tree/master/Samples/BackgroundTransfer – Razor Mar 30 '17 at 11:34
  • 3
    @Souvik Ghosh use of await before getasync will make the app wait till the file is downloaded. using task.run wont help as httpclient.getasync will switch to UI thread even when you use configureAwait(false). Cancellation token does not have any part to play here as 10 mb file will take longer than downloading 2mb file. – Razor Mar 30 '17 at 11:42