首页 > 解决方案 > Xamarin Android ReadOnlyStream 读取时缓冲区太小

问题描述

我正在尝试执行一个非常简单的操作 - 从 Internet 下载文件(在 Xamarin.Forms 中)。该文件很大,所以我从流(即ReadOnlyStream)中读取它并将其写入FileStream. 下载大文件时设置较大的缓冲区大小是可取的,因为下载过程会更快。我注意到的是,实际读取缓冲区的上限仅为 8 kB,这使得下载过程非常缓慢。这是已知的限制还是错误?有什么解决方法吗?我的示例代码是

var url = @"https://speed.hetzner.de/100MB.bin";
        var httpClient = new HttpClient();
        var s = await httpClient.GetStreamAsync(url);
        var fs = new FileStream(
            Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "myfile"), FileMode.Create);
        var got = 0;
        var total = 0L;
        var buffer = new byte[1024 * 1024];
        while ((got = await s.ReadAsync(buffer, 0, buffer.Length)) != 0)
        {
            Debug.WriteLine($"<||> {got}\t|\t{total}");
            total += got;
            await fs.WriteAsync(buffer, 0, got);
        }

相同的代码在 iOS 上按预期工作。

编辑:感觉就像是 HttpClient 实现的问题。您可以在 Android 项目属性中设置它。推荐的(Android)有这个 8 kB 的上限,而 Managed 有 16 kB,仍然太小。

EDIT2:HttpClient.SendAsync用于下载文件“修复”速度问题。但是,不可能将它用于大文件,因为所有内容都首先加载到内存中。

EDIT3:特定平台也无济于事。相同的 8192 字节上限。

public async Task Download(string urlString)
    {
        int count;
        try
        {
            URL url = new URL(urlString);
            URLConnection connection = url.OpenConnection();
            await connection.ConnectAsync();

            InputStream input = new BufferedInputStream(url.OpenStream(),1024*1024);

            var output = new MemoryStream();

            var data = new byte[1024 * 1024];

            while ((count = await input.ReadAsync(data, 0, data.Length)) != -1)
            {
                Debug.WriteLine($"<||> {count}");
                await output.WriteAsync(data, 0, count);
            }

            await output.FlushAsync();

            output.Close();
            input.Close();
        }
        catch (Exception e)
        {
            Debug.WriteLine($"<||> {e}");
        }
    }

标签: c#androidxamarinxamarin.formsdotnet-httpclient

解决方案


推荐阅读