Laravel通过Ajax发邮件调用getRealPath()报string调用方法错误
问题原因
- 你通过Ajax上传图片时没有正确处理文件类请求的提交规则,控制器中用
$request->get('image')获取到的是字符串格式的内容(可能是base64编码、临时路径字符串等),而非Laravel预设的Illuminate\Http\UploadedFile文件实例。只有UploadedFile实例支持调用getRealPath()、getClientOriginalName()这类对象方法,字符串调用对象方法就会触发当前报错。 - 附带注意:携带文件的Ajax请求必须用
FormData对象封装参数,同时设置contentType: false、processData: false,否则文件会被自动序列化为字符串传递到后端。
修复方案
1. 修改控制器获取文件的代码
Laravel中只有file()方法可以正确获取上传的文件实例,把$request->get('image')替换为$request->file('image'),可额外增加文件上传校验规则避免非法提交:
public function SendEmailByLaravel(Request $request) { // 增加文件上传校验 $request->validate([ 'image' => 'nullable|file|mimes:jpg,png,gif,pdf|max:10240' ]); $data = [ 'subject' => $request->get('subject'), 'email' => $request->get('email'), 'body' => $request->get('body'), 'image' => $request->file('image') ]; Mail::to($data['email'])->send(new PersonalMail($data)); }
2. 调整前端Ajax提交逻辑
确保用FormData封装所有提交参数,配置正确的请求参数,以jQuery Ajax为例:
// 初始化FormData对象 let submitData = new FormData(); submitData.append('subject', '邮件主题内容'); submitData.append('email', 'recipient@test.com'); submitData.append('body', '邮件正文内容'); // 从文件选择框获取选中的文件 submitData.append('image', $('#upload-input')[0].files[0]); $.ajax({ url: '你的后端接口地址', type: 'POST', data: submitData, contentType: false, // 不自定义Content-Type,让浏览器自动生成带boundary的请求头 processData: false, // 不序列化FormData对象 success: res => { console.log('邮件发送成功') } })
3. (可选兼容优化)邮件类增加类型判断
可以在邮件类中增加类型校验逻辑,避免异常场景下的报错:
public function build() { $body = $this->data['body']; $subject = $this->data['subject']; $mail = $this->subject($subject)->view('Emails.PersonalMail', compact('subject', 'body')); // 仅当image为UploadedFile实例时才执行附件逻辑 if ($this->data['image'] instanceof \Illuminate\Http\UploadedFile) { $mail->attach($this->data['image']->getRealPath(), [ 'as' => $this->data['image']->getClientOriginalName() ]); } return $mail; }
内容的提问来源于stack exchange,提问作者ahmad almasri
相关产品推荐
相关产品推荐

