如何强制knitr::include_graphics()使用项目相对路径保障输出可移植性
问题根因
该异常的本质是knitr::include_graphics()默认会调用normalizePath()解析输入路径,软链接会被展开为真实物理路径:
- 当使用
html_document格式时默认开启self_contained: true,图片会被转成base64内嵌到输出文件,不会暴露路径问题 - 当使用
revealjs_presentation且关闭self_contained时,解析后的绝对路径会直接写入img标签的src属性,导致可移植性失效
可行解决方案
方案1:开启全局相对路径配置
knitr 1.37及以上版本提供了全局配置项,直接强制所有图片输出相对路径,不会解析软链接:
在Rmd的setup代码块中加入以下配置:
options(knitr.graphics.rel_path = TRUE)
配置后include_graphics()会直接保留你传入的相对路径,不会做额外转换。
方案2:自定义图片处理钩子绕开路径解析
如果上述配置不生效,可通过fig.process钩子完全接管路径输出逻辑,强制返回你需要的相对路径:
knitr::opts_chunk$set( fig.process = function(origin_path) { # 可根据需求写自定义路径转换逻辑,这里直接返回目标相对路径即可 "graphics/example.jpg" } )
方案3:直接输出原生HTML标签(最可控)
如果不需要knitr处理图片相关的额外逻辑,可直接用HTML标签输出图片,完全绕开knitr的路径解析:
# 支持自定义尺寸、alt文本等所有属性 htmltools::img(src = "./graphics/example.jpg", width = "80%", alt = "示例图")
knitr路径控制核心逻辑
- knit过程的默认工作目录为Rmd文件所在目录,可通过
knitr::opts_knit$set(root.dir = 目标路径)修改,所有相对路径的解析都基于该目录 include_graphics()默认会校验路径有效性并调用系统接口标准化路径,软链接、相对路径都会被展开为绝对物理路径- 输出格式的
self_contained参数决定了资源是内嵌还是外链:开启时资源直接嵌入文件,不会生成路径;关闭时会将标准化后的路径写入输出文件
适配targets流水线的额外建议
你可以在调用rmarkdown::render()时通过params参数传入资源根路径,所有图片路径都基于该参数拼接,避免硬编码,完全适配流水线的目录结构:
# 调用render时传入参数 rmarkdown::render( "test.Rmd", envir = new.env(), params = list(res_root = "./graphics/") )
在Rmd中通过params$res_root拼接图片路径即可。
内容的提问来源于stack exchange,提问作者Richard J. Acton
相关产品推荐
相关产品推荐

