7 个不稳定版本

0.4.0 2023 年 8 月 30 日
0.3.1 2022 年 3 月 21 日
0.2.1 2021 年 11 月 16 日
0.1.1 2021 年 11 月 15 日

压缩 类别中排名 148

Download history 540/week @ 2024-03-13 553/week @ 2024-03-20 282/week @ 2024-03-27 640/week @ 2024-04-03 374/week @ 2024-04-10 312/week @ 2024-04-17 346/week @ 2024-04-24 420/week @ 2024-05-01 303/week @ 2024-05-08 409/week @ 2024-05-15 376/week @ 2024-05-22 362/week @ 2024-05-29 220/week @ 2024-06-05 474/week @ 2024-06-12 809/week @ 2024-06-19 177/week @ 2024-06-26

每月下载 1,719
retrom-service 中使用

MIT 许可证

27KB
336 行代码(不包括注释)

Zipit

crates.io Documentation

🗄️ 将 zip 归档创建并流式传输到 AsyncWrite 🗄️

zipit = "0.3"

功能

  • 从多个 AsyncRead 对象中即时流式传输归档。
  • 单次读取/查找实现(CRC 和文件大小在流式传输时计算,之后发送)。
  • 归档大小预先计算(如果您想在流式传输前设置 Content-Length 则很有用)。
  • futurestokio 兼容的 AsyncRead / AsyncWrite。根据需要启用 futures-async-iotokio-async-io 功能。

限制

  • 无压缩(仅存储方法)。
  • 仅文件(无目录)。
  • 无可自定义的外部文件属性。

示例

文件系统

使用 tokio::fs::File 将 zip 归档写入文件系统

use std::io::Cursor;
use tokio::fs::File;
use zipit::{Archive, FileDateTime};

#[tokio::main]
async fn main() {
    let file = File::create("archive.zip").await.unwrap();
    let mut archive = Archive::new(file);
    archive.append(
        "file1.txt".to_owned(),
        FileDateTime::now(),
        &mut Cursor::new(b"hello\n".to_vec()),
    ).await.unwrap();
    archive.append(
        "file2.txt".to_owned(),
        FileDateTime::now(),
        &mut Cursor::new(b"world\n".to_vec()),
    ).await.unwrap();
    archive.finalize().await.unwrap();
}

Hyper

将 zip 归档作为 hyper 响应流式传输

use std::io::Cursor;
use hyper::{header, Body, Request, Response, Server, StatusCode};
use tokio::io::duplex;
use tokio_util::io::ReaderStream;
use zipit::{archive_size, Archive, FileDateTime};

async fn zip_archive(_req: Request<Body>) -> Result<Response<Body>, hyper::http::Error> {
    let (filename_1, mut fd_1) = (String::from("file1.txt"), Cursor::new(b"hello\n".to_vec()));
    let (filename_2, mut fd_2) = (String::from("file2.txt"), Cursor::new(b"world\n".to_vec()));
    let archive_size = archive_size([
        (filename_1.as_ref(), fd_1.get_ref().len()),
        (filename_2.as_ref(), fd_2.get_ref().len()),
    ]);

    let (w, r) = duplex(4096);
    tokio::spawn(async move {
        let mut archive = Archive::new(w);
        archive
            .append(
                filename_1,
                FileDateTime::now(),
                &mut fd_1,
            )
            .await
            .unwrap();
        archive
            .append(
                filename_2,
                FileDateTime::now(),
                &mut fd_2,
            )
            .await
            .unwrap();
        archive.finalize().await.unwrap();
    });

    Response::builder()
        .status(StatusCode::OK)
        .header(header::CONTENT_LENGTH, archive_size)
        .header(header::CONTENT_TYPE, "application/zip")
        .body(Body::wrap_stream(ReaderStream::new(r)))
}

依赖

~0–1.7MB
~28K SLoC