修复从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
相关产品推荐
相关产品推荐

