使用 File.stream 时图像大小的差异

Difference in image size using File.stream

我正在使用 send_resp(200,content)

发送图像文件作为响应

我已经使用 Stream 延迟加载文件

File.stream!(fullpath)
|> Stream.map(fn e -> e end) 
|> Enum.reduce(<<>>, fn x,acc  -> acc <> x end)

我在磁盘上的原始文件大小是 1615829 字节。

如果我这样做 File.read(fullpath)(预先加载),我会得到大小为 1615829 的确切文件。

但是使用File.stream接收到的图像文件是1615792(少了37字节)。

图像因此变得模糊。

我遗漏了哪些位?我在这里使用 File.stream 正确吗?

很难说出您显示的代码之外有什么问题,但这段代码肯定 a) 很好 b) 毫无意义。

Enum.reduce/3(因为 Enum 模块中的所有函数)确实终止了流。也就是说,行

fullpath
|> File.stream!()
|> Stream.map(& &1) 
|> Enum.reduce("", &2 <> &1)

File.read!/1 基本相同(可能效率较低)。您可能会检查他们 return 正确的预期结果,但他们 立即

with :ok <- File.write!("test.txt", "a\x00\n\x01b") do
  "test.txt"
  |> File.stream!()
  |> Stream.map(& &1)
  |> Enum.reduce("", & &2 <> &1)
end
#⇒ <<97, 0, 10, 1, 98>>

也就是说,您最好选择将工作委派给现有的助手,例如 Plug.Conn.send_file/5. If you still want to reimplement this functionality, you should use iodata built-in type to construct your object, it’s faster than binaries (and Plug.Conn.send_resp/3 欣然接受。)

拆分和重新连接二进制文件不会使其 运行 更快。

来自https://hexdocs.pm/elixir/File.html#stream!/3

File.stream!(path, modes \ [], line_or_bytes \ :line)

The line_or_bytes argument configures how the file is read when streaming, by :line (default) or by a given number of bytes. When using the :line option, CRLF line breaks (" ") are normalized to LF (" ").

因此,默认情况下,它将文件视为文本并规范化换行符。这会使结果变小。

请尝试以下操作:

File.stream!(fullpath, [], 128 * 1024)