【问题标题】:FileStream corrupt zip - SignalR StreamFileStream 损坏的 zip - SignalR Stream
【发布时间】:2021-07-03 00:31:17
【问题描述】:

我正在尝试获取在客户端上创建的 zip 文件,并通过 Hub 流将该文件分块上传。当流结束时,我尝试打开文件,windows 状态它无法打开,{file name} 无效。

在执行 File.WriteAllBytes(path, bytes[]) 时,字节数组在分块之前在客户端上写得很好。查看流式文件和 File.WriteAllBytes 时,文件大小相同。

我没有想法......

客户端

private async IAsyncEnumerable<byte[]> StreamBytes(byte[] bytes)
    {
        //this works and I'm able to open the file it creates.
        File.WriteAllBytes(@"C:\test.zip", bytes);
        long fileSize = bytes.Length;
        long fileWrite = 0;

        while (fileSize != 0)
        {
            byte[] buffer = fileSize > ByteHelper.BUFFER_SIZE ? new byte[ByteHelper.BUFFER_SIZE] : new byte[fileSize];
            Array.Copy(bytes, buffer, buffer.Length);

            fileSize -= buffer.Length;
            fileWrite += buffer.Length;

            var bufResult = await Task.FromResult(buffer);
            yield return bufResult;
        }
    }

服务器端

public async Task UploadCommandResultStream(IAsyncEnumerable<byte[]> byteChunk, int commandQueueKey, string folder)
    {
        var path = Path.Combine(_settings.UploadPath, folder);
        if (Directory.Exists(path) == false)
        {
            Directory.CreateDirectory(path);
        }

        var file = Path.Combine(path, $"{commandQueueKey}.zip");
        long bytesread = 0;
        try
        {
            //this creates a file but can't open
            using (FileStream fs = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.Read, ByteHelper.BUFFER_SIZE))
            {
                await foreach (var bytes in byteChunk)
                {
                    fs.Write(bytes, 0, bytes.Length);
                    bytesread += bytes.Length;
                }
            }
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "asyncwrite");
        }
    }

【问题讨论】:

    标签: c# .net-core signalr


    【解决方案1】:

    您可能需要改变方法;新提议的功能Async Streams in C# 8 使异步模式更加灵活,但我认为这种方法不能正确结束或刷新 FileStream 对象。请尝试使用以下语法移动最后一个方法:

    //this creates a file but can't open
    using (FileStream fs = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.Read, ByteHelper.BUFFER_SIZE, true))
    {
       await fs.WriteAsync(bytes, 0, bytes.Length);
    }
    

    【讨论】:

    • 添加 isAsync true 不起作用。我很有希望,但没有。
    【解决方案2】:

    我相信您的文件只是没有完全刷新最后一个缓冲区。试试改成这个

    //this creates a file but can't open
    using (FileStream fs = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.Read, ByteHelper.BUFFER_SIZE))
    {
        await foreach (var bytes in byteChunk)
        {
            fs.Write(bytes, 0, bytes.Length);
            bytesread += bytes.Length;
        }
        fs.Flush(); //or await fs.FlushAsync()
    }
    

    【讨论】:

    • 我也试过了……没用。不过我确实找到了解决办法……请参阅我的新帖子。
    【解决方案3】:

    好的,我想出了答案。它是客户端的 IAsyncEnumerable。作为测试,我在客户端将文件写入磁盘,我知道这很有效,然后打开 FileStream 并读取块产生结果。

    仍在调查原始客户端代码错误的原因,但现在这 100% 有效。

    代码需要清理一下,因为修剪缓冲区可以处理得更好,但写得很快。

    客户端

    private async IAsyncEnumerable<byte[]> StreamBytes(byte[] bytes)
        {
            string fileName = @"test.zip";
            File.WriteAllBytes(fileName, bytes);
    
            using(var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read, ByteHelper.BUFFER_SIZE, true))
            {
                long fileSize = fs.Length;
                int totalBytesRead = 0;
                byte[] buffer = new byte[ByteHelper.BUFFER_SIZE];
    
                while (fileSize > 0)
                {
                    fs.Seek(totalBytesRead, SeekOrigin.Begin);
                    var bytesRead = await fs.ReadAsync(buffer, 0, ByteHelper.BUFFER_SIZE);
                    if (bytesRead == 0)
                        break;
    
                    totalBytesRead += bytesRead;
                    fileSize -= bytesRead;
    
                    if (bytesRead != ByteHelper.BUFFER_SIZE)
                    {
                        byte[] trimmedBuffer = new byte[bytesRead];
                        Array.Copy(buffer, trimmedBuffer, bytesRead);
    
                        buffer = new byte[bytesRead];
                        Array.Copy(trimmedBuffer, buffer, bytesRead);
                    }
    
                    yield return buffer;
                }
            }
            //long fileSize = bytes.Length;
            //long fileWrite = 0;
    
            //while (fileSize != 0)
            //{
            //    byte[] buffer = fileSize > ByteHelper.BUFFER_SIZE ? new byte[ByteHelper.BUFFER_SIZE] : new byte[fileSize];
            //    Array.Copy(bytes, buffer, buffer.Length);
    
            //    fileSize -= buffer.Length;
            //    fileWrite += buffer.Length;
    
            //    var bufResult = await Task.FromResult(buffer);
            //    yield return bufResult;
            //}
        }
    

    【讨论】:

    猜你喜欢
    • 2011-01-12
    • 2012-10-07
    • 2015-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-01
    相关资源
    最近更新 更多