通过HTML <input type=file>读取文件存储后作为邮件附件发送相关问题
问题解答
一、方法合理性及更简便实现方案
你当前使用FileReader读取文件再传输的方法可行但不是最优选择,存在编码适配风险、传输体积偏大等问题,更简便的实现方式如下:
直接使用FormData对象封装表单字段+文件二进制流,不需要手动读取文件内容,Axios会自动设置对应的请求头,PHP后端可直接通过$_FILES全局变量获取上传的文件,省略手动解析文件内容、写入本地的冗余步骤。
二、文件为空的原因
你当前代码的核心问题出在前端文件读取逻辑:
你调用了reader.readAsText(file, "UTF-8")以UTF-8文本格式读取文件,仅对纯文本类文件有效,.pdf、.docx等都是二进制格式文件,用文本格式读取时会出现编码错误,导致读取到的内容损坏或为空,写入后端后自然生成空文件。
三、修复方案
推荐方案:使用FormData传输文件
前端代码修改
不用FileReader读取,直接把文件塞入FormData即可:
async function() { return new Promise((resolve, reject) => { const formData = new FormData(); // 填充普通表单字段 formData.append('email', $('#email').val()); formData.append('header', $('#header').val()); formData.append('content', $('#content').val()); // 填充选中的文件 const file = $('#files')[0].files[0]; if (file) { formData.append('selectedfile', file); } // 正常通过Axios发送FormData即可,会自动适配multipart/form-data格式 resolve(formData); }); }
后端PHP代码修改
直接从$_FILES中获取上传的临时文件,移动到目标存储路径即可:
// 判断文件是否上传成功 if (isset($_FILES['selectedfile']) && $_FILES['selectedfile']['error'] == UPLOAD_ERR_OK) { $tmpPath = $_FILES['selectedfile']['tmp_name']; $targetPath = "../storage/" . $_FILES['selectedfile']['name']; // 移动临时文件到目标路径 move_uploaded_file($tmpPath, $targetPath); } // 其余普通表单字段直接从$_POST中获取 $email = $_POST['email']; $header = $_POST['header']; $content = $_POST['content'];
兼容原有逻辑的修复方案
如果你坚持要用原有FileReader的实现方案,可按如下方式修改:
- 前端把
reader.readAsText(file, "UTF-8")修改为reader.readAsDataURL(file),以base64格式读取二进制文件内容,避免编码损坏 - 后端写入文件前先对base64内容解码:
$content = json_decode($request->getContent()); $selectedfile = $content->selectedfile; // 去除base64头部标识,再解码内容 $fileContent = base64_decode(preg_replace('#^data:.*?;base64,#', '', $selectedfile[0])); file_put_contents("../storage/" . $selectedfile[1], $fileContent);
内容的提问来源于stack exchange,提问作者Elias
相关产品推荐
相关产品推荐

