【问题标题】:Corrupted images when using Read and Write streams to save files使用读写流保存文件时损坏的图像
【发布时间】:2016-04-11 12:14:49
【问题描述】:

各位程序员们好

我正在使用 Xamarin (iOS) 的应用程序中实现下载功能,以获取正在下载的文件的进度。

我使用的代码是来自网络的各种示例,显示相同的原理,最大的编码风格差异。它们都在 System.IO.File 上使用相同的 ReadAsync 和 WriteAsync 函数,并使用字节数组作为缓冲区。

但无论我转向哪个示例,它都会导致图片上出现不同的伪影,如下所示:

(原创/下载)

我似乎找不到发生这种情况的任何原因。 我尝试了不同的方法,看看是什么触发了这种情况。我发现将缓冲区更改为更大的大小(比如 10240)会导致更多的伪影,而更小的缓冲区(比如 1024)会导致更少的伪影。

在调试不同的东西时,我找到了一种“避免”这种情况发生的“方法”,但这包括在 WriteAsync 刚刚完成后添加一个任务延迟,持续 20 毫秒(在代码中注释掉) - 不是解决方案我想一起去,但告诉问题可能在于两个流的使用(在女巫我的知识是“仅限基本用法”)。 我也尝试使用非异步方法,但结果相同。

希望有人能告诉我我在这里做错了什么,以及为什么。

提前致谢

public async Task<bool> MakeDownloadRequestAsync(string url, string destination, Action<string, long, long, float> progress = null) {
    if (_downloadHttpClient == null) {
        _downloadHttpClient = new HttpClient (new NativeMessageHandler());
    }

    bool finished = false;

    try {
        var result = await _downloadHttpClient.GetAsync(url, HttpCompletionOption.ResponseHeadersRead);

        long receivedBytes = 0;
        long totalBytes = result.Content.Headers.ContentLength.HasValue ? result.Content.Headers.ContentLength.Value : 0;

        System.Diagnostics.Debug.WriteLine ("Started download file: {0}", url);

        using (var stream = await _downloadHttpClient.GetStreamAsync (url))
        {
            byte[] buffer = new byte[4096];
            var filename = Path.GetFileName (url);
            var writeStream = _fileStore.OpenWrite (Path.Combine(destination, filename));

            while(true)
            {
                int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);

                if (bytesRead == 0)
                {
                    finished = true;
                    System.Diagnostics.Debug.WriteLine ("Finished downloading file: {0}", url);
                    break;
                }


                await writeStream.WriteAsync(buffer, 0, buffer.Length);
                //Task.Delay(20);
                receivedBytes += bytesRead;

                if (progress != null)
                {
                    progress.Invoke(url, receivedBytes, totalBytes, (float)receivedBytes/(float)totalBytes);
                }
            }

            writeStream.Dispose();
            stream.Dispose();
        }

    } catch (Exception e) {
        System.Diagnostics.Debug.WriteLine (e);
    }


    return finished;
}

【问题讨论】:

  • 能否提供手术前后的准确图片文件?

标签: c# xamarin xamarin.ios httpclient filestream


【解决方案1】:

你的问题可能是这一行:

await writeStream.WriteAsync(buffer, 0, buffer.Length);

应该是:

await writeStream.WriteAsync(buffer, 0, bytesRead);

您的代码正在写入整个缓冲区...无论实际读取了多少字节。相反,您应该只写入实际读取的字节数。

【讨论】:

  • 当然,这很有意义。我预计缓冲区长度的变化取决于它的内容,但这将是一个固定的大小(正如我所要求的那样)。感谢一百万道格!
  • 很高兴帮助佩尔。这是一个常见的错误。如果我可以再发表评论,则不需要 stream.Dispose() 调用。使用 using 语句时,会自动调用 Dispose。
  • 我知道双 stream.Dispose() 是另一个失败的尝试,看看什么可以解决问题。但是感谢您引起我的注意:)
【解决方案2】:

我无法弄清楚上面的源代码有什么问题。但是我有一个 sn-p 可以下载文件并保存,这对我来说非常有用。

public async static Task DownloadByteArray(string url)
{
    using (var client = new HttpClient(new NativeMessageHandler())) 
    {
        try
        {
            using (var response = await client.GetAsync(new Uri (url))) 
            {
                using (var responseContent = response.Content) 
                {
                    var byteArray = await responseContent.ReadAsByteArrayAsync();
                    var folderPath = System.IO.Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.MyDocuments), "Downloads");
                    System.IO.Directory.CreateDirectory (folderPath);

                    var extension = url.Split ('.').Last ();
                    string filename = System.IO.Path.Combine (folderPath, DateTime.Now.ToString("yyyyMMddhhmmss")+"."+ extension);
                    File.WriteAllBytes (filename,byteArray);
                }
            }
        }
        catch (Exception ex)
        {

        }
    }
}

如果您对此 sn-p 有任何疑问,我会解释。

【讨论】:

  • 感谢您的建议。这是下载到内存中的字节数组。我可能下载的文件可能比可用内存大。也不给我当前正在下载的文件的进度。
猜你喜欢
  • 2021-09-26
  • 2017-07-16
  • 2015-09-22
  • 1970-01-01
  • 1970-01-01
  • 2023-03-19
  • 1970-01-01
  • 2018-08-14
  • 1970-01-01
相关资源
最近更新 更多