如何在Laravel 5中向MSSQL存储BLOB类型图片
解决Laravel 5.4将图片存入MSSQL BLOB字段的问题
我来帮你搞定这个问题,你遇到的核心问题是:Eloquent的create方法会把你传入的Image字段值当作普通字符串处理,不会执行你写的OPENROWSET子查询。下面给你两种可行的解决方案:
方案一:直接读取文件二进制内容存入BLOB
既然你已经把文件保存到了storage/app/avatars目录,那可以直接读取这个文件的二进制内容,然后赋值给Image字段。这种方式不需要依赖OPENROWSET,更符合Laravel的常规操作逻辑:
修改你的控制器store方法如下:
public function store() { $file = request()->file('avatar'); $ext = $file->guessClientExtension(); $nameWithExt = request('name') . '.' . $ext; // 保存文件到storage目录(这一步你已经实现了) $filePath = $file->storeAs('avatars', $nameWithExt); // 读取文件的二进制内容 $imageContent = file_get_contents(storage_path('app/' . $filePath)); Employee::create([ 'EmplNr' => request('emplNr'), 'Name' => request('name'), 'Image' => $imageContent ]); return back(); }
这种方法的好处是不需要额外配置SQL Server的权限,直接通过PHP读取文件内容存入BLOB,兼容性更强。
方案二:使用原生SQL执行OPENROWSET插入
如果你坚持要用OPENROWSET的方式插入,就不能用Eloquent的create方法了,需要用Laravel的查询构造器执行原生SQL语句。注意要确保SQL Server的服务账号有访问你文件路径的权限:
public function store() { $file = request()->file('avatar'); $ext = $file->guessClientExtension(); $nameWithExt = request('name') . '.' . $ext; // 保存文件到storage目录 $file->storeAs('avatars', $nameWithExt); $fullPath = storage_path('app/avatars/' . $nameWithExt); // 转义路径中的反斜杠,避免SQL语法错误 $escapedPath = str_replace('\\', '\\\\', $fullPath); // 执行原生SQL插入语句 \DB::statement("INSERT INTO EmployeeImages (EmplNr, Name, Image) VALUES(?, ?, (SELECT * FROM OPENROWSET(BULK N'{$escapedPath}', SINGLE_BLOB) rs))", [ request('emplNr'), request('name') ]); return back(); }
这里要特别注意路径的转义:SQL Server的字符串中,反斜杠需要用双反斜杠表示,否则会被当作转义字符处理,导致路径识别错误。
为什么你之前的写法无效?
当你用Employee::create()传入Image字段为SELECT ...字符串时,Eloquent会自动对这个字符串进行转义处理,最终存入数据库的只是这段SQL语句的文本内容,而不是执行该语句得到的二进制图片数据。只有直接执行原生SQL时,数据库才会解析并执行OPENROWSET子查询,获取图片的二进制内容。
内容的提问来源于stack exchange,提问作者Greg Ostry
相关产品推荐
相关产品推荐

