stream.CopyAsync(streamDestination) 其抛出Stream不支持读取异常
stream.CopyAsync(streamDestination) its throw Stream does not support reading exception
我正在尝试为 gzip 压缩文件,但是在压缩之后我需要生成 gzip 字节以生成 base64 字符串。
然而,当我尝试将 gzip 流复制到内存流时,它抛出异常 Stream does not support reading。
我找不到解决这个问题的方法,有人可以帮助我吗?
遵循以下代码:
public static async Task<Tuple<bool, string, string>> CompressToGzipBase64(this IFormFile formFile, Language language)
{
var filePath = formFile.FileName + ".gz";
try
{
await using var gzipFileStream = File.OpenWrite(formFile.FileName + ".gz");
await using var gZipStream = new GZipStream(gzipFileStream, CompressionMode.Compress);
await formFile.CopyToAsync(gZipStream);
var bytesOfFile = await ConverteStreamToByteArray(gZipStream);
var fileInBase64 = Convert.ToBase64String(bytesOfFile);
File.Delete(filePath);
return new Tuple<bool, string, string>(true, fileInBase64, string.Empty);
}
catch (Exception e)
{
File.Delete(filePath);
return language switch
{
Language.PtBr => new Tuple<bool, string, string>(false, string.Empty,
"Ocorreu um erro durante a conversão do arquivo para o formato Gzip. Por favor tente a operação novamente!"),
Language.EnUs => new Tuple<bool, string, string>(false, string.Empty,
"An error occurred while converting the file to Gzip format. Please try the operation again!"),
Language.EsEs => new Tuple<bool, string, string>(false, string.Empty,
"Se produjo un error al convertir el archivo a formato Gzip. ¡Intente la operación nuevamente!"),
_ => new Tuple<bool, string, string>(false, string.Empty, string.Empty)
};
}
}
private static async Task<byte[]> ConverteStreamToByteArray(GZipStream stream)
{
await using var ms = new MemoryStream();
await stream.CopyToAsync(ms);
return ms.ToArray();
}
您无法从压缩模式下的 GzipStream 中读取,因为它是一个转换流,而不是数据所在的位置。您的数据实际上在 FileStream 中,因此您需要从中读取数据。
但是你甚至不需要 FileStream,因为你没有对文件做任何事情,因为你最后要删除它。 FileStream 只是不必要的,因为它需要写入非常低效的磁盘。
那就这样吧:
await using var compressedStream = new MemoryStream();
await using var gZipStream = new GZipStream(compressedStream, CompressionMode.Compress);
await formFile.CopyToAsync(gZipStream);
var bytesOfFile = compressedStream.ToArray();
var fileInBase64 = Convert.ToBase64String(bytesOfFile);
此外,我建议使用值元组而不是元组,因为它们更简洁、更高效且更易读,因为您可以命名元素。
因此您的整个代码可以改进为:
public static async Task<(bool success, string base64, string error)> CompressToGzipBase64(this IFormFile formFile, Language language)
{
try
{
await using var compressedStream = new MemoryStream();
await using var gZipStream = new GZipStream(compressedStream, CompressionMode.Compress);
await formFile.CopyToAsync(gZipStream);
var bytesOfFile = compressedStream.ToArray();
var fileInBase64 = Convert.ToBase64String(bytesOfFile);
return (true, fileInBase64, string.Empty);
}
catch (Exception e)
{
return language switch
{
Language.PtBr => (false, string.Empty,
"Ocorreu um erro durante a conversão do arquivo para o formato Gzip. Por favor tente a operação novamente!"),
Language.EnUs => (false, string.Empty,
"An error occurred while converting the file to Gzip format. Please try the operation again!"),
Language.EsEs => (false, string.Empty,
"Se produjo un error al convertir el archivo a formato Gzip. ¡Intente la operación nuevamente!"),
_ => (false, string.Empty, string.Empty)
};
}
}
你可以这样调用它:
var (success, base64, error) = await formFile.CompressToGzipBase64(Language.EnUs);
另一个建议:不要只是丢弃异常消息。您应该在某处记录异常或在错误消息中包含异常文本。这使得抛出异常时的调试和生活变得更加容易,因为您不需要猜测 error/exception 真正发生了什么。
我正在尝试为 gzip 压缩文件,但是在压缩之后我需要生成 gzip 字节以生成 base64 字符串。
然而,当我尝试将 gzip 流复制到内存流时,它抛出异常 Stream does not support reading。
我找不到解决这个问题的方法,有人可以帮助我吗?
遵循以下代码:
public static async Task<Tuple<bool, string, string>> CompressToGzipBase64(this IFormFile formFile, Language language)
{
var filePath = formFile.FileName + ".gz";
try
{
await using var gzipFileStream = File.OpenWrite(formFile.FileName + ".gz");
await using var gZipStream = new GZipStream(gzipFileStream, CompressionMode.Compress);
await formFile.CopyToAsync(gZipStream);
var bytesOfFile = await ConverteStreamToByteArray(gZipStream);
var fileInBase64 = Convert.ToBase64String(bytesOfFile);
File.Delete(filePath);
return new Tuple<bool, string, string>(true, fileInBase64, string.Empty);
}
catch (Exception e)
{
File.Delete(filePath);
return language switch
{
Language.PtBr => new Tuple<bool, string, string>(false, string.Empty,
"Ocorreu um erro durante a conversão do arquivo para o formato Gzip. Por favor tente a operação novamente!"),
Language.EnUs => new Tuple<bool, string, string>(false, string.Empty,
"An error occurred while converting the file to Gzip format. Please try the operation again!"),
Language.EsEs => new Tuple<bool, string, string>(false, string.Empty,
"Se produjo un error al convertir el archivo a formato Gzip. ¡Intente la operación nuevamente!"),
_ => new Tuple<bool, string, string>(false, string.Empty, string.Empty)
};
}
}
private static async Task<byte[]> ConverteStreamToByteArray(GZipStream stream)
{
await using var ms = new MemoryStream();
await stream.CopyToAsync(ms);
return ms.ToArray();
}
您无法从压缩模式下的 GzipStream 中读取,因为它是一个转换流,而不是数据所在的位置。您的数据实际上在 FileStream 中,因此您需要从中读取数据。
但是你甚至不需要 FileStream,因为你没有对文件做任何事情,因为你最后要删除它。 FileStream 只是不必要的,因为它需要写入非常低效的磁盘。
那就这样吧:
await using var compressedStream = new MemoryStream();
await using var gZipStream = new GZipStream(compressedStream, CompressionMode.Compress);
await formFile.CopyToAsync(gZipStream);
var bytesOfFile = compressedStream.ToArray();
var fileInBase64 = Convert.ToBase64String(bytesOfFile);
此外,我建议使用值元组而不是元组,因为它们更简洁、更高效且更易读,因为您可以命名元素。
因此您的整个代码可以改进为:
public static async Task<(bool success, string base64, string error)> CompressToGzipBase64(this IFormFile formFile, Language language)
{
try
{
await using var compressedStream = new MemoryStream();
await using var gZipStream = new GZipStream(compressedStream, CompressionMode.Compress);
await formFile.CopyToAsync(gZipStream);
var bytesOfFile = compressedStream.ToArray();
var fileInBase64 = Convert.ToBase64String(bytesOfFile);
return (true, fileInBase64, string.Empty);
}
catch (Exception e)
{
return language switch
{
Language.PtBr => (false, string.Empty,
"Ocorreu um erro durante a conversão do arquivo para o formato Gzip. Por favor tente a operação novamente!"),
Language.EnUs => (false, string.Empty,
"An error occurred while converting the file to Gzip format. Please try the operation again!"),
Language.EsEs => (false, string.Empty,
"Se produjo un error al convertir el archivo a formato Gzip. ¡Intente la operación nuevamente!"),
_ => (false, string.Empty, string.Empty)
};
}
}
你可以这样调用它:
var (success, base64, error) = await formFile.CompressToGzipBase64(Language.EnUs);
另一个建议:不要只是丢弃异常消息。您应该在某处记录异常或在错误消息中包含异常文本。这使得抛出异常时的调试和生活变得更加容易,因为您不需要猜测 error/exception 真正发生了什么。