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

Phoenix LiveView文件上传未保存原文件:文件名无扩展名异常

问题原因及解决方案

问题出在你直接使用了LiveView生成的临时上传文件名作为最终保存的文件名。Phoenix LiveView生成的临时文件本身就是无扩展名的随机命名(比如live_view_upload-1733165679-200177911668-2),所以Path.basename(path)自然会返回无扩展名的结果。

要保留原始文件的扩展名,你需要从上传的entry对象中获取用户上传的原始文件名信息,具体修改如下:

修改后的代码

def handle_event("save", _params, socket) do
    Logger.info("UploadLive.Upload: save")

    uploaded_files =
      consume_uploaded_entries(socket, :avatar, fn %{path: path}, entry ->
        # 获取用户上传的原始文件名
        original_filename = entry.client_name
        # 提取原始文件的扩展名
        file_ext = Path.extname(original_filename)
        # 生成安全的目标文件名:原始文件名主体 + 唯一标识 + 扩展名(避免重名覆盖)
        safe_filename = "#{Path.rootname(original_filename)}-#{System.unique_integer([:positive])}#{file_ext}"
        dest = Path.join(Application.app_dir(:live_jobzz, "priv/static/uploads"), safe_filename)
        
        Logger.info("UploadLive.Upload: path #{path}")
        Logger.info("UploadLive.Upload: dest #{dest}")

        # 确保uploads目录存在(增强代码健壮性)
        File.mkdir_p!(Path.dirname(dest))
        File.cp!(path, dest)
        {:ok, ~p"/uploads/#{safe_filename}"}
      end)

    {:noreply, update(socket, :uploaded_files, &(&1 ++ uploaded_files))}
  end

关键说明

  • entry.client_name:存储了用户上传的原始文件名(比如my-photo.jpg),通过它可以拿到正确的文件扩展名。
  • System.unique_integer([:positive]):生成唯一整数后缀,避免多个用户上传同名文件时互相覆盖。如果业务场景不需要防重,也可以直接使用原始文件名,但生产环境建议保留该逻辑。
  • File.mkdir_p!(Path.dirname(dest)):确保目标目录存在,避免因目录未提前创建导致的文件拷贝失败。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 21:27:35