You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

修复从Actix Web端点下载的归档文件内权限拒绝问题

问题分析与解决:tokio-tar生成的归档文件权限异常

权限异常的原因

你通过Header::new_gnu()创建的tar文件头,默认权限位是0(无任何读写执行权限),而你的代码仅设置了文件大小和校验和,未显式指定文件权限参数,因此解压后的文件会继承这个默认权限,导致无法正常打开。另外文件显示的修改时间为1970年1月1日,也是因为Header默认使用Unix纪元起始时间,未设置实际的修改/访问时间。

解决方法

需要在创建Header后,手动设置合理的文件权限,同时可补充设置文件修改时间让归档属性更合理:

修改后的代码示例

use std::time::SystemTime;
use tokio_tar::{Builder, Header};
use bytes::Bytes;
use actix_web::{HttpResponse};

async fn generate_archive(files: impl Iterator<Item = (&str, Bytes)>) -> actix_web::Result<HttpResponse> {
    let mut ar = Builder::new(Vec::new());

    for (path, file) in files {
        let mut header = Header::new_gnu();
        header.set_size(file.len() as u64);
        
        // 设置普通文件权限:用户可读写,组和其他用户只读
        header.set_mode(0o644);
        
        // 设置当前时间为文件修改时间,替换默认的纪元起始时间
        let now = SystemTime::now()
            .duration_since(SystemTime::UNIX_EPOCH)
            .map_err(|_| actix_web::error::ErrorInternalServerError("Failed to get system time"))?;
        header.set_mtime(now.as_secs());
        
        header.set_cksum();
        ar.append_data(&mut header, path, file.as_ref()).await?;
    }
    let ar_data = ar.into_inner().await?;

    Ok(HttpResponse::Ok()
        .append_header(("Content-Disposition", "attachment; filename=\"archive.tar\""))
        .body(ar_data))
}

额外说明

  • set_mode接收八进制格式的权限值,这是Unix系统的标准权限表示方式:
    • 普通文件常用0o644(用户读写,其他只读)或0o664(用户/组读写,其他只读)
    • 目录常用0o755(用户读写执行,其他读执行)
  • 如果你的文件列表包含目录,需要额外通过header.set_entry_type(tar::EntryType::Directory)标记目录类型,并设置对应权限
  • 若你是从本地文件读取内容生成归档,也可以直接从原文件的metadata中获取权限和时间,再同步到Header中,保持归档文件与原文件属性一致

内容的提问来源于stack exchange,提问作者Finlay Weber

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 05:53:30