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
相关产品推荐
相关产品推荐

