使用 Phoenix 提供多个动态图像时出现问题(有些负载,有些不负载)
Problem serving multiple dynamic images with Phoenix (some load, some dont)
技术:Phoenix 1.4.9
问题:在带有 "img" 标签的网页中提供上传的图像,导致一些能够加载而另一些则不能。
已尝试检查图像 link,但图像 link(a.e。/image/1 或 /image/2)每次加载都没有问题。
强制缓存清除也不能证明问题的任何迹象。
如果人们想自己玩代码,这里是 git 存储库:https://github.com/WannesFransen1994/phoenix-dynamic-images
我认为重要的代码:
控制器:
def index(conn, _params) do
images = Repo.all(Image)
render(conn, "index.html", images: images)
end
def create(conn, %{"upload" => %Plug.Upload{} = up}) do
{:ok, _u} = up |> ImageContext.create_image()
redirect(conn, to: Routes.page_path(conn, :index))
end
def display(conn, %{"id" => id}) do
i = Repo.get(Image, id)
conn |> put_resp_content_type(i.content_type) |> send_file(200, Image.local_path(i))
end
ImageContext.ex
def create_image(%{filename: _, path: tmp_path, content_type: _} = upload) do
hash = File.stream!(tmp_path, [], 2048) |> Image.sha256()
with {:ok, %File.Stat{size: size}} <- File.stat(tmp_path),
data_merged <- Map.from_struct(upload) |> Map.merge(%{size: size, hash: hash}),
{:ok, upload_cs} <- %Image{} |> Image.changeset(data_merged) |> Repo.insert(),
:ok <- tmp_path |> File.cp(Image.local_path(upload_cs)) do
{:ok, upload_cs}
else
{:error, reason} -> Repo.rollback(reason)
end
end
图像架构(没有变更集等...)
schema "images" do
field :filename, :string
field :content_type, :string
field :hash, :string
field :size, :integer
end
def local_path(%Image{} = upload) do
[@upload_directory, "#{upload.id}-#{upload.filename}"] |> Path.join()
end
输出(在图像显示 link 上)有效,但是当我转到生成所有带有 "img" 标签的图像的概览页面时,它们随机加载失败(有时他们都工作,有时 none,有时一半,有时一个工作而其他人不工作)
奇怪的是,当您检查日志时,您会收到以下错误:
** (exit) an exception was raised:
** (File.Error) could not read file stats "uploads/images/1-user_upload_3.png": no such file or directory
当文件在那里并且当您重新加载或分开查看图像时它可以工作。
EXTRA:问题的图像。同一个页面,只是重新加载了两次:
解决方案是使用绝对路径。
显然 Phoenix 有时会更改当前工作目录,例如在重新加载代码时,因此相对路径会失败。
归功于 Nobbz (Slack) 和 Jose Valim(Git 期)。
技术:Phoenix 1.4.9 问题:在带有 "img" 标签的网页中提供上传的图像,导致一些能够加载而另一些则不能。
已尝试检查图像 link,但图像 link(a.e。/image/1 或 /image/2)每次加载都没有问题。
强制缓存清除也不能证明问题的任何迹象。
如果人们想自己玩代码,这里是 git 存储库:https://github.com/WannesFransen1994/phoenix-dynamic-images
我认为重要的代码: 控制器:
def index(conn, _params) do
images = Repo.all(Image)
render(conn, "index.html", images: images)
end
def create(conn, %{"upload" => %Plug.Upload{} = up}) do
{:ok, _u} = up |> ImageContext.create_image()
redirect(conn, to: Routes.page_path(conn, :index))
end
def display(conn, %{"id" => id}) do
i = Repo.get(Image, id)
conn |> put_resp_content_type(i.content_type) |> send_file(200, Image.local_path(i))
end
ImageContext.ex
def create_image(%{filename: _, path: tmp_path, content_type: _} = upload) do
hash = File.stream!(tmp_path, [], 2048) |> Image.sha256()
with {:ok, %File.Stat{size: size}} <- File.stat(tmp_path),
data_merged <- Map.from_struct(upload) |> Map.merge(%{size: size, hash: hash}),
{:ok, upload_cs} <- %Image{} |> Image.changeset(data_merged) |> Repo.insert(),
:ok <- tmp_path |> File.cp(Image.local_path(upload_cs)) do
{:ok, upload_cs}
else
{:error, reason} -> Repo.rollback(reason)
end
end
图像架构(没有变更集等...)
schema "images" do
field :filename, :string
field :content_type, :string
field :hash, :string
field :size, :integer
end
def local_path(%Image{} = upload) do
[@upload_directory, "#{upload.id}-#{upload.filename}"] |> Path.join()
end
输出(在图像显示 link 上)有效,但是当我转到生成所有带有 "img" 标签的图像的概览页面时,它们随机加载失败(有时他们都工作,有时 none,有时一半,有时一个工作而其他人不工作)
奇怪的是,当您检查日志时,您会收到以下错误:
** (exit) an exception was raised:
** (File.Error) could not read file stats "uploads/images/1-user_upload_3.png": no such file or directory
当文件在那里并且当您重新加载或分开查看图像时它可以工作。
EXTRA:问题的图像。同一个页面,只是重新加载了两次:
解决方案是使用绝对路径。
显然 Phoenix 有时会更改当前工作目录,例如在重新加载代码时,因此相对路径会失败。
归功于 Nobbz (Slack) 和 Jose Valim(Git 期)。