FileStream 损坏的 zip - SignalR Stream
FileStream corrupt zip - SignalR Stream
我正在尝试获取在客户端上创建的 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");
}
}
您可能需要改变方法;新提议的功能 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);
}
我相信您的文件没有完全清除最后一个缓冲区。试试改成这个
//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()
}
好的,我找到答案了。它是客户端的 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;
//}
}
我正在尝试获取在客户端上创建的 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");
}
}
您可能需要改变方法;新提议的功能 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);
}
我相信您的文件没有完全清除最后一个缓冲区。试试改成这个
//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()
}
好的,我找到答案了。它是客户端的 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;
//}
}