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

