创建一个 URL 下载命令以用于例如 \includegraphics

创建一个 URL 下载命令以用于例如 \includegraphics

我们刚才讨论的是一个可能有点不切实际的想法。是否有可能将 URL 支持修补到其中,graphicx.sty或者是否有一个软件包可以在更大范围内支持这一点(我可以想象它对 和类似产品都会很有用pdfpageslistings

显然,它需要\write18支持,但至少graphicx.sty某些操作已经需要它,所以这应该不是问题。我假设在一般情况下,需要定义一个宏。可以通过定义一个具有/ /? 规则的扩展graphicx来作弊。.urlcurlwget

理想情况下\includegraphics{http://domain/file.png}是可行的,但我不明白graphicx如果不进行大规模修补,这将如何适应当前环境。或者我可以看到\includegraphics{\grab{http://domain/file.png}}\includegraphics{http://domain/file.png.url}

有人做过这个吗?想分享一下吗?这样做合理吗?

答案1

我不太确定您设想的工作原理,也不相信有此必要。我认为更合理的做法是先将图像下载到本地文件夹(而不是每次运行时都重新下载),并使用您选择的文件名,而不是根据 URL 自动得出文件名,然后仅包含该文件名。

以下是一个概念证明,假设curl可用且\write18已启用:

\documentclass{article}
\usepackage{graphicx}
\newcommand*{\grabto}[2]{\IfFileExists{#2}{}{\immediate\write18{curl \detokenize{#1 -o #2}}}}

\grabto{https://i.stack.imgur.com/Bil0Q.png}{test.png}

\begin{document}
    \includegraphics{test.png}
\end{document}

(图片来自你另一个问题的回答。)

答案2

好的,受到 Joseph Wright 使用 lua 的想法的启发,我尝试使用纯 lua 来实现这一点。

\newcommand{\grabto}[2]{#2\ifluatex%
\directlua 0 {
local uri   = "\luatexluaescapestring{#1}"
local fname = "\luatexluaescapestring{#2}"
local job   = "\luatexluaescapestring{\jobname}"
local file  = io.open(fname, 'r')
if file \string~= nil then 
  io.close(file)
else 
  % This detection isn't foolproof because this will happily write to a 0200 
  % file for example but latex can't read it and confusingly won't barf, but 
  % this case is pathologic and depending on posix is somewhat unpreferable
  file = io.open(fname, 'w')
  if file == nil then 
    print("(" .. job .. " file " .. fname .. " does exist already but cannot be read)")
  else 
    require("ltn12")
    local outputsink = ltn12.sink.file(file)
    require("socket.url")
    local parsed = socket.url.parse(uri, {scheme = 'file'})
    if parsed.scheme ==  'http' then
      require("socket.http")
      socket.http.request { url = uri, sink = outputsink, } 
    elseif parsed.scheme == 'ftp' then
      require("socket.ftp")
      socket.ftp.get { url = uri, sink = outputsink, } 
    else 
      % file scheme doesn't make sense because this branch indicates we 
      % at least couldn't read the file.
      tex.error("Don't know how to download this sorry")
      % This situation is a little annoying because we may have 
      % accidentally created a file and can't delete it in case our heuristics
      % failed
    end 
  end
end}%
\else%
% fallback
\fi}

这是我接触的第一个 lua,因此非常感谢改进。我相信它适用于我能想到的所有情况。正如评论中提到的,如果 luatex 不是编译器,我试图想出一个合理的后备方案,但很快就变得很糟糕。

我也改变了界面,所以它返回了#2,因为然后我可以写 \includegraphics{\luagrabto{https://i.stack.imgur.com/Bil0Q.png}{test.png}} 这对于 lua 部分和基本的后备来说工作得很好,但\includegraphic在某些部分确实很挑剔,而且绝对不喜欢我摆弄它\hyper@normalize以确保这不会因为奇怪的 url 而崩溃。

相关内容