Elixir/Phoenix相对路径上传文件失败,求助配置方法
解决Elixir/Phoenix上传文件时相对路径失效的问题
我之前也踩过一模一样的坑!你碰到的:enoent错误,本质是相对路径指向的目录找不到——不是真的目录没创建,而是Phoenix运行时的工作目录和你预期的不一样:直接写"media/..."是相对于应用启动时的当前工作目录,而非项目根目录,所以系统找不到目标路径。
下面是一步步的解决方案:
1. 用应用内置工具获取可靠路径
别硬编码绝对路径(比如/Users/myaccount/MyApp/...),也别依赖不稳定的相对路径,我们用Elixir提供的工具获取应用priv目录的绝对路径,这样不管应用在哪里运行都能精准定位目标目录:
:code.priv_dir(:my_app)会返回你应用priv目录的绝对路径(比如/Users/myaccount/MyApp/priv)- 在此基础上,我们可以构造出
priv/static/media的绝对路径:Path.join(:code.priv_dir(:my_app), "static/media")
2. 修正控制器代码
首先要确保目标目录存在(不然还是会报:enoent),再用构造好的绝对路径移动文件:
defmodule MyAppWeb.UploadController do use MyAppWeb, :controller def create(conn, %{"user" => user_params}) do IO.inspect(user_params) if upload = user_params["photo"] do extension = Path.extname(upload.filename) # 获取应用priv下media目录的绝对路径 media_dir = Path.join(:code.priv_dir(:my_app), "static/media") # 递归创建目录(不存在则自动生成) File.mkdir_p!(media_dir) # 拼接最终的文件存储路径 target_path = Path.join(media_dir, "profile#{extension}") case File.cp(upload.path, target_path) do {:ok, _result} -> conn |> put_flash(:info, "File Uploaded successfully.") |> redirect(to: upload_path(conn, :index)) {:error, reason} -> IO.inspect(reason, label: "Upload failed reason") conn |> put_flash(:error, "File Upload failed!") |> redirect(to: upload_path(conn, :index)) end else # 处理未选择文件的场景 conn |> put_flash(:error, "Please select a file to upload.") |> redirect(to: upload_path(conn, :index)) end end end
3. 修正Endpoint的静态文件配置
你原来的Plug.Static配置里from: "media/"是错误的,需要指向正确的媒体目录,同样用绝对路径保证可靠性:
plug Plug.Static, at: "/", from: :fish_pot, gzip: false, only: ~w(css fonts images js favicon.ico robots.txt) # 修正后的静态文件服务配置 plug Plug.Static, at: "/uploads", from: Path.join(:code.priv_dir(:fish_pot), "static/media"), gzip: false
额外注意事项
- 确保Phoenix进程对
priv/static/media目录有写入权限,否则会碰到:eperm权限错误。 - 如果是部署到生产环境(比如Docker、Heroku),本地存储的文件会在容器重启/应用重新部署时丢失,建议改用云存储服务(比如AWS S3、Cloudinary)来持久化文件。
内容的提问来源于stack exchange,提问作者tajihiro
相关产品推荐
相关产品推荐

