mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-17 18:27:49 +00:00
feat: auto-extract support
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
use async_compression::tokio::bufread::{BzDecoder, GzipDecoder, XzDecoder, ZlibDecoder, ZstdDecoder};
|
||||
use tokio::io::{self, AsyncRead, BufReader};
|
||||
use tokio_stream::StreamExt;
|
||||
use tokio_tar::Archive;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum CompressionFormat {
|
||||
Gzip, //.gz
|
||||
Bzip2, //.bz2
|
||||
// Lz4, //.lz4
|
||||
Zip,
|
||||
Xz, //.xz
|
||||
Zlib, //.z
|
||||
Zstd, //.zst
|
||||
Unknown,
|
||||
}
|
||||
|
||||
impl CompressionFormat {
|
||||
pub fn from_extension(ext: &str) -> Self {
|
||||
match ext {
|
||||
"gz" => CompressionFormat::Gzip,
|
||||
"bz2" => CompressionFormat::Bzip2,
|
||||
// "lz4" => CompressionFormat::Lz4,
|
||||
"zip" => CompressionFormat::Zip,
|
||||
"xz" => CompressionFormat::Xz,
|
||||
"zlib" => CompressionFormat::Zlib,
|
||||
"zst" => CompressionFormat::Zstd,
|
||||
_ => CompressionFormat::Unknown,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_decoder<R>(&self, input: R) -> io::Result<Box<dyn AsyncRead + Send + Unpin>>
|
||||
where
|
||||
R: AsyncRead + Send + Unpin + 'static,
|
||||
{
|
||||
let reader = BufReader::new(input);
|
||||
|
||||
let decoder: Box<dyn AsyncRead + Send + Unpin + 'static> = match self {
|
||||
CompressionFormat::Gzip => Box::new(GzipDecoder::new(reader)),
|
||||
CompressionFormat::Bzip2 => Box::new(BzDecoder::new(reader)),
|
||||
// CompressionFormat::Lz4 => Box::new(Lz4Decoder::new(reader)),
|
||||
CompressionFormat::Zlib => Box::new(ZlibDecoder::new(reader)),
|
||||
CompressionFormat::Xz => Box::new(XzDecoder::new(reader)),
|
||||
CompressionFormat::Zstd => Box::new(ZstdDecoder::new(reader)),
|
||||
_ => return Err(io::Error::new(io::ErrorKind::InvalidInput, "Unsupported file format")),
|
||||
};
|
||||
|
||||
Ok(decoder)
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn decompress<R, F>(input: R, format: CompressionFormat, mut callback: F) -> io::Result<()>
|
||||
where
|
||||
R: AsyncRead + Send + Unpin + 'static,
|
||||
F: AsyncFnMut(tokio_tar::Entry<Archive<Box<dyn AsyncRead + Send + Unpin + 'static>>>) -> std::io::Result<()> + Send + 'static,
|
||||
{
|
||||
// 打开输入文件
|
||||
// println!("format {:?}", format);
|
||||
|
||||
let decoder = format.get_decoder(input)?;
|
||||
|
||||
// let reader: BufReader<R> = BufReader::new(input);
|
||||
|
||||
// // 根据文件扩展名选择解压器
|
||||
// let decoder: Box<dyn AsyncRead + Send + Unpin> = match format {
|
||||
// CompressionFormat::Gzip => Box::new(GzipDecoder::new(reader)),
|
||||
// CompressionFormat::Bzip2 => Box::new(BzDecoder::new(reader)),
|
||||
// // CompressionFormat::Lz4 => Box::new(Lz4Decoder::new(reader)),
|
||||
// CompressionFormat::Zlib => Box::new(ZlibDecoder::new(reader)),
|
||||
// CompressionFormat::Xz => Box::new(XzDecoder::new(reader)),
|
||||
// CompressionFormat::Zstd => Box::new(ZstdDecoder::new(reader)),
|
||||
// // CompressionFormat::Zip => Box::new(DeflateDecoder::new(reader)),
|
||||
// _ => {
|
||||
// return Err(io::Error::new(io::ErrorKind::InvalidInput, "Unsupported file format"));
|
||||
// }
|
||||
// };
|
||||
|
||||
let mut ar = Archive::new(decoder);
|
||||
let mut entries = ar.entries().unwrap();
|
||||
while let Some(entry) = entries.next().await {
|
||||
let f = match entry {
|
||||
Ok(f) => f,
|
||||
Err(e) => {
|
||||
println!("Error reading entry: {}", e);
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
// println!("{}", f.path().unwrap().display());
|
||||
callback(f).await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// #[tokio::test]
|
||||
// async fn test_decompress() -> io::Result<()> {
|
||||
// use std::path::Path;
|
||||
// use tokio::fs::File;
|
||||
|
||||
// let input_path = "/Users/weisd/Downloads/wsd.tar.gz"; // 替换为你的压缩文件路径
|
||||
|
||||
// let f = File::open(input_path).await?;
|
||||
|
||||
// let Some(ext) = Path::new(input_path).extension().and_then(|s| s.to_str()) else {
|
||||
// return Err(io::Error::new(io::ErrorKind::InvalidInput, "Unsupported file format"));
|
||||
// };
|
||||
|
||||
// match decompress(
|
||||
// f,
|
||||
// CompressionFormat::from_extension(ext),
|
||||
// |entry: tokio_tar::Entry<Archive<Box<dyn AsyncRead + Send + Unpin>>>| async move {
|
||||
// let path = entry.path().unwrap();
|
||||
// println!("Extracted: {}", path.display());
|
||||
// Ok(())
|
||||
// },
|
||||
// )
|
||||
// .await
|
||||
// {
|
||||
// Ok(_) => println!("解压成功!"),
|
||||
// Err(e) => println!("解压失败: {}", e),
|
||||
// }
|
||||
|
||||
// Ok(())
|
||||
// }
|
||||
Reference in New Issue
Block a user