中文 | English
Go 语言实现的 ASAR 打包/解包库与命令行工具,功能对齐 Electron 官方 asar(node-asar)。可用于:
- 打包任意应用目录为
.asar - 解包
.asar到指定目录 - 读取并解析 ASAR 头部(Pickle + JSON)
- 列出归档内的所有路径
- 计算文件完整性(整文件哈希与 4MB 分块哈希,
SHA256)
- 作为库使用(Go 模块):
go get github.com/dcboy/go-asar
- 构建命令行工具:
go build -o ./bin/go-asar ./cmd/asar
- 打包目录为
.asar:
./bin/go-asar pack --src ./path/to/app --dest ./app.asar
- 解包
.asar到目录:
./bin/go-asar extract --archive ./app.asar --dest ./unpacked
- 列出
.asar文件内的路径(库方法):
files, _ := asar.ListPackage("./app.asar", false)
for _, f := range files { fmt.Println(f) }
CreatePackage(src, dest string) error- 用默认选项打包
src目录到dest.asar
- 用默认选项打包
CreatePackageWithOptions(src, dest string, options CreateOptions) error- 支持选项:
Dot:是否包含隐藏文件(默认包含)Ordering:指定插入顺序的文件列表路径Pattern:匹配模式(当前实现主要用于兼容行为)Unpack:按文件 glob 规则解包到dest.asar.unpackedUnpackDir:按目录前缀/简易 glob 规则解包到dest.asar.unpacked
- 支持选项:
ExtractAll(archivePath, dest string) error- 将
.asar全部解包到dest
- 将
ExtractFile(archivePath, filename string, followLinks bool) ([]byte, error)- 读取归档内单个文件的二进制内容
ListPackage(archivePath string, isPack bool) ([]string, error)- 列出所有路径;
isPack=true时附带pack/unpack标记
- 列出所有路径;
GetRawHeader(archivePath string) (ArchiveHeader, error)- 返回原始 Pickle 头解析结果(包含 JSON 字符串与嵌套目录结构)
示例:
package main
import (
"fmt"
"github.com/dcboy/go-asar/asar"
)
func main() {
if err := asar.CreatePackage("./app", "./app.asar"); err != nil {
panic(err)
}
files, _ := asar.ListPackage("./app.asar", false)
for _, f := range files { fmt.Println(f) }
}
-
pack
- 语法:
asar pack <dir> <output> [--ordering <file>] [--unpack <glob>] [--unpack-dir <glob|prefix>] [--exclude-hidden] - 说明:
--ordering <file>指定插入顺序文件(每行一个路径,支持a:b前缀格式,行为与 node-asar 对齐)--unpack <glob>匹配到的文件不打包,直接复制到<output>.unpacked--unpack-dir <glob|prefix>匹配到的目录或以该前缀开头的目录不打包,目录内文件复制到<output>.unpacked--exclude-hidden排除隐藏文件(任一路径段首字符为.),与 node-asar 的exclude-hidden一致
- 示例:
./bin/go-asar pack ./app ./app.asar./bin/go-asar pack ./app ./app.asar --exclude-hidden./bin/go-asar pack ./app ./app.asar --ordering ./ordering.txt./bin/go-asar pack ./app ./app.asar --unpack "*.png"./bin/go-asar pack ./app ./app.asar --unpack-dir "assets/**"
- 语法:
-
list
- 语法:
asar list <archive> [-i | --is-pack] - 说明:开启
--is-pack时,在每个路径前输出pack :或unpack :标记 - 示例:
./bin/go-asar list ./app.asar./bin/go-asar list ./app.asar --is-pack
- 语法:
-
extract-file
- 语法:
asar extract-file <archive> <filename> - 说明:提取单个文件到当前目录的
basename(filename),与 node-asar 行为一致 - 示例:
./bin/go-asar extract-file ./app.asar dir1/file1.txt
- 语法:
-
extract
- 语法:
asar extract <archive> <dest> - 说明:解压整个
.asar到指定目录 - 示例:
./bin/go-asar extract ./app.asar ./unpacked
- 语法:
- 头部格式:
- 与
asar规范一致:先写入 8 字节的 size-pickle(payload 长度),随后写入 header-pickle(包含 JSON 字符串),再按顺序写入所有“打包文件”的内容。 - 文件节点中的
offset为内容在文件尾部开始处的偏移(相对于 header 之后的连续数据)。
- 与
- 完整性信息:
algorithm: "SHA256",blockSize: 4MB,blocks: []string逐块哈希,hash为整文件哈希。
- 安全检查:
- 解包时校验写出路径是否越界(防路径穿越),链接是否指向包外路径。
- 路径相对化:
- 归档内部记录统一为相对于打包根目录的路径,处理符号链接时优先使用字符串前缀裁切。
- 打包:
./bin/go-asar pack --src <源目录> --dest <输出asar路径>
- 解包:
./bin/go-asar extract --archive <asar路径> --dest <输出目录>
- 已实现核心能力(打包、解包、列出、完整性、头部解析),默认包含隐藏文件。
Unpack/UnpackDir支持常见场景的匹配;如需完全复刻minimatch的全部语义可在后续扩展。- “从流打包”(
createPackageFromStreams)暂未暴露为 Go API,如有需要可继续补充。
- 构建:
go build ./... - 示例验证:可使用
node-asar/test/input/packthis进行打包与解包,并对比diff -r。
go build -o ./bin/go-asar ./cmd/asar
./bin/go-asar pack --src ./node-asar/test/input/packthis --dest ./tmp.packthis.asar
./bin/go-asar extract --archive ./tmp.packthis.asar --dest ./tmp.extract
# 可选对比
# diff -r ./tmp.extract ./node-asar/test/input/packthis
- MIT(与上游一致)。
- Electron 官方
asar与其node-asar参考实现。
go-asar is a Go implementation of the ASAR pack/unpack library and CLI aligned with Electron’s asar (node-asar).
- Pack any app directory to
.asar - Extract
.asarto a destination - Read and parse ASAR header (Pickle + JSON)
- List all paths in the archive
- Compute file integrity (whole file hash and 4MB block hashes,
SHA256)
Library:
go get github.com/dcboy/go-asar
CLI:
go build -o ./bin/go-asar ./cmd/asar
Pack:
./bin/go-asar pack ./path/to/app ./app.asar
Extract:
./bin/go-asar extract ./app.asar ./unpacked
List:
files, _ := asar.ListPackage("./app.asar", false)
for _, f := range files { fmt.Println(f) }
-
pack
- Syntax:
asar pack <dir> <output> [--ordering <file>] [--unpack <glob>] [--unpack-dir <glob|prefix>] [--exclude-hidden] - Notes:
--ordering <file>specifies insertion order file (one path per line; supportsa:bprefix format), aligned with node-asar--unpack <glob>matches files to be copied to<output>.unpackedinstead of packing--unpack-dir <glob|prefix>matches directories (glob or prefix) to be unpacked to<output>.unpacked--exclude-hiddenexcludes hidden files (any path segment starting with.)
- Examples:
./bin/go-asar pack ./app ./app.asar./bin/go-asar pack ./app ./app.asar --exclude-hidden./bin/go-asar pack ./app ./app.asar --ordering ./ordering.txt./bin/go-asar pack ./app ./app.asar --unpack "*.png"./bin/go-asar pack ./app ./app.asar --unpack-dir "assets/**"
- Syntax:
-
list
- Syntax:
asar list <archive> [-i | --is-pack] - Notes: when
--is-packis set, each path is prefixed withpack :orunpack : - Examples:
./bin/go-asar list ./app.asar./bin/go-asar list ./app.asar --is-pack
- Syntax:
-
extract-file
- Syntax:
asar extract-file <archive> <filename> - Notes: extracts a single file to
basename(filename)in current directory - Example:
./bin/go-asar extract-file ./app.asar dir1/file1.txt
- Syntax:
-
extract
- Syntax:
asar extract <archive> <dest> - Notes: extracts the whole archive to destination
- Example:
./bin/go-asar extract ./app.asar ./unpacked
- Syntax:
CreatePackage(src, dest string) errorCreatePackageWithOptions(src, dest string, options CreateOptions) errorExtractAll(archivePath, dest string) errorExtractFile(archivePath, filename string, followLinks bool) ([]byte, error)ListPackage(archivePath string, isPack bool) ([]string, error)GetRawHeader(archivePath string) (ArchiveHeader, error)
- Header format: size-pickle (payload length) + header-pickle (JSON string), followed by file contents in order
- Integrity:
SHA256for whole file and 4MB blocks - Safety: path traversal checks when extracting; symlink target validation
- Relative paths: normalized to archive root; symlinks handled with string prefix trimming then
filepath.Relfallback