跳转到内容

从文件读取与写入磁盘

复制本页

文件读写是图像处理管线的起点与终点。虽然四个入口底层都调用 libvips 的格式加载器(如 jpegload、pngload、webpload)和保存器(如 jpegsave、webpsave),但它们在如何传入加载参数以及是否提供直接写文件函数上存在明显差异。

用于文件读写示例的苏州东方之门夜景 JPEG 原图
输入文件:JPEG1938 × 1292,610,191 字节
从文件加载并以 WebP 格式写回磁盘的夜景输出图
输出文件:WebP1938 × 1292,399,106 字节(govips 参考输出)

在生产环境中,建议显式传入加载参数(Import Parameters),例如访问模式(AccessSequential)与损坏像素的容错级别(FailOn),而不是只使用无参默认加载。

还需要注意:govips 的 ImageRef 没有 SaveToFile 方法。在 govips 中落盘有两种方式:一是调用 ExportWebp / ExportJpeg / ExportPng 拿到 []byte 后交给标准库 os.WriteFile;二是打开 *os.File 后调用 govips v2.19.0 新增的 SaveToWriterWebp 等流式写出方法。

package main
import (
"fmt"
"os"
"github.com/davidbyttow/govips/v2/vips"
)
func main() {
if err := vips.Startup(nil); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
defer vips.Shutdown()
importParams := vips.NewImportParams()
importParams.Access.Set(vips.AccessSequential)
importParams.FailOn.Set(vips.FailOnError)
image, err := vips.LoadImageFromFile("input.jpg", importParams)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
defer image.Close()
exportParams := vips.NewWebpExportParams()
exportParams.Quality = 82
exportParams.StripMetadata = true
data, _, err := image.ExportWebp(exportParams)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
if err := os.WriteFile("output.webp", data, 0o644); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}
维度 govips v2.20.0 sharp 0.35.5 pyvips 3.2.0 vips CLI 8.17.3
默认文件加载入口 NewImageFromFile(path) sharp(path) Image.new_from_file(path) 直接传文件路径参数
带参文件加载入口 LoadImageFromFile(path, params) sharp(path, options) Image.new_from_file(path, **kwargs) 'path[key=val,...]'
直接写文件路径 无(使用 Export* + os.WriteFile 或 SaveToWriter*) .toFile(outPath)(返回 OutputInfo) .write_to_file(outPath, **kwargs) 'outPath[key=val,...]'
同路径原位覆盖保护 调用方自行保证 直接拒绝并报错 Cannot use same file for input and output 不拦截,但在顺序读取下会截断源文件导致失败 不拦截,但在顺序读取下会截断源文件导致失败

在加载阶段传入提示参数,可以让解码器在读取文件时跳过不必要的工作:

  • 访问模式(Access Mode):vips.AccessSequential / sequentialRead: true / access="sequential" 告诉 libvips 按从上到下的扫描线流式拉取像素;适合单次缩放、裁剪和转码,但不适合需要反向读取行的操作。
  • 容错策略(Fail-on Policy):控制遇到截断或损坏数据时的行为,支持 none(尽可能解码)、truncated(文件截断时报错)、error(解码错误时报错)、warning(任何警告均报错,适合严格校验不可信上传)。
  • 按需解码页与 DPI:对 GIF/WebP 动图或 PDF/TIFF 文档,可在加载时指定 Page 与 NumPages(n=-1 表示加载全部帧)以及矢量光栅化 Density(DPI)。

使用临时文件原子替换目标文件

Section titled “使用临时文件原子替换目标文件”

当业务需要更新磁盘上已有的图片路径时,推荐采用“写临时文件 + 原子重命名”模式:

func writeAtomically(targetPath string, data []byte) error {
tmpPath := targetPath + ".tmp"
if err := os.WriteFile(tmpPath, data, 0o644); err != nil {
return err
}
return os.Rename(tmpPath, targetPath)
}