dot net maui and dropbox api: Error in call to API function "files/download"

438 Views Asked by At

I have visual studio 2022 and am using dot net maui building on the base example by James Montemagno. I am calling the dropbox api (visual studio package) to download a file and it works fine on windows, but when I switch to the android emulator I get this Error:

Error in call to API function "files/download":Bad HTTP "Content-Type" header: "application/x-www-form-urlencoded". Expecting one of "text/plain; charset=utf-8","application/octet-stream","application/octest-stream;charset=utf-8"

My code is very straightforward and listed below. I have googled this error and there were previous fixes but none seem to apply to the latest version of Visual Studio - hence the CreateClient()

using Dropbox.Api.Files;
using Dropbox.Api.Users;
public HttpClient CreateClient()
{
    #if __ANDROID__
        return new HttpClient(new Xamarin.Android.Net.AndroidMessageHandler());
    #else
        return new HttpClient();
    #endif
}
public async Task GetInfoFromDropbox()
{
    string szFileName = "Somefile.dat";
    string szDropBoxToken = "myDropboxToken";
    httpClient = CreateClient();
    var objDbx = new DropboxClient(szDropBoxToken, new DropboxClientConfig() { HttpClient = httpClient });

    // Code fails here      
    var result = await objDbx.Files.DownloadAsync(szFileName);

    // carries on working if windows
    var result2 = await result.GetContentAsStreamAsync();
}
2

There are 2 best solutions below

0
On BEST ANSWER

I found the answer and it was a little more complicated than the supplied answer by user 21374054:

I needed the conditional #if ANDROID as compiling for other platforms failed - otherwise the code is similar, BUT there was also a thread error which I resolved in the ReadDropbox routine

so here is the code:

#if __ANDROID__
public class MyAndroidMessageHandler : Xamarin.Android.Net.AndroidMessageHandler
{
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        if (request.RequestUri.AbsolutePath.Contains("files/download"))
        {
            request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
        }
        return base.SendAsync(request, cancellationToken);
    }
}
#endif

public HttpClient CreateClient()
    {
#if __ANDROID__
      return new HttpClient(new MyAndroidMessageHandler());
#else
        return new HttpClient();
#endif
    }

public async Task<DataTable> ReadDropboxFile(string szFileName)
{
    DataSet dataset = new DataSet();
    DataTable datatable = new DataTable();
    string szDropBoxToken = m_szDropBoxToken;
    httpClient = CreateClient();
    var objDbx = new DropboxClient(szDropBoxToken, new DropboxClientConfig() { HttpClient = httpClient });

    // this trick uses another thread to avoid an android error of using the main thread
    await Task.Run(async () => {
        var result = await objDbx.Files.DownloadAsync(szFileName);
        var result2 = await result.GetContentAsStreamAsync();

        dataset.ReadXml(result2);
    });

    datatable = dataset.Tables[0];
    return datatable;
}
0
On

for .net maui please use this code:

  public class MyAndroidMessageHandler : HttpClientHandler
    {
        protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            if (request.RequestUri.AbsolutePath.Contains("files/download"))
            {
                request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
            }
            return await base.SendAsync(request, cancellationToken);
        }
    }

    public DropboxClient GetClient()
    {
        if (DeviceInfo.Current.Platform == DevicePlatform.Android)
        {
            return new DropboxClient(AccessToken, new DropboxClientConfig()
            {
                HttpClient = new HttpClient(new MyAndroidMessageHandler())
            });
        }
        return new DropboxClient(AccessToken);
    }