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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:47:19