You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Elixir Arc本地上传图片无法访问及url生成多余前缀如何解决

问题解决办法

问题1:静态资源路由不存在报错

这个问题是因为Phoenix默认没有将uploads目录纳入静态资源服务目录,需要修改项目下lib/ok_backend_web/endpoint.ex中的Plug.Static配置:
找到如下配置段:

plug Plug.Static,
  at: "/",
  from: :ok_backend,
  gzip: false,
  only: ~w(assets fonts images favicon.ico robots.txt)

将uploads添加到only列表,或者新增extra_dirs配置即可:

plug Plug.Static,
  at: "/",
  from: :ok_backend,
  gzip: false,
  only: ~w(assets fonts images favicon.ico robots.txt uploads)

修改后重启服务即可直接通过URL访问上传的图片。

问题2:生成的URL文件名多出前缀

错误原因

  1. Arc的url/2工作逻辑:传入(已存储的文件名,scope)两个参数后,会重新执行你定义的storage_dir/2和filename/2函数,拼接asset_host、存储目录、最终文件名生成完整访问路径,所以传入的scope必须和存储时的scope完全一致才能得到正确路径。
  2. 你调用Uploader.url/2时传入的scope与存储文件时传入的scope不一致:存储时用的scope是<user_id>_<8位随机数>,而生成URL时你只传了params["user_id"]作为scope,filename/2函数会把你传入的短scope再拼到文件名前面,导致多出前缀。
  3. 你的控制器代码存在笔误:with语句中拿到的返回值是fname,但render的时候用了未定义的filename变量。

修复方案

  1. 存储文件成功后,建议把完整的scope(<user_id>_<8位随机数>)和文件名一起落库保存,方便后续生成访问路径。
  2. 调用Uploader.url/2时,传入存储时使用的完整scope,而不是只传user_id,同时修正控制器变量笔误:
def upload(conn, params) do
  random_number = random_n_char_number_string(8)
  scope = params["user_id"] <> "_" <> random_number
  with {:ok, fname} <- Uploader.store({params["image"], scope}) do
    # 传入完整scope生成正确URL
    file_url = Uploader.url({fname, scope})
    render(conn, "upload.json", params: %{"status" => :success, "filename" => fname, "url" => file_url})
  end
end

如果不想每次都保存完整scope,也可以调整filename/2的逻辑,避免重复拼接前缀,或者直接根据存储的文件名和目录手动拼接访问路径。

内容的提问来源于stack exchange,提问作者sooon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 15:06:03