数据库异常– yii \ db \ Exception
Error Info: Array
(
[0] => HY000
[1] => 102
[2] => Incorrect syntax near 'PK'. [102] (severity 15) [INSERT INTO [ORDERS] ([ID], [STATUS], [ZIPFILE], [COLOR], [PRICE]) VALUES (87, 1,'PK]
[3] => -1
[4] => 15
)
by原因:PDOException SQLSTATE [HY000]:常规错误:102'PK'附近的语法不正确。[102](严重性15)[插入[订单]([ID],[状态],[ZIPFILE],[颜色],[价格])值(87、1,'PK)
在yii2应用程序中,我试图使用file_get_uploads php函数上传zip文件,首先将zip转换为二进制文件,然后将其保存到SQL Server数据库的'ZIPFILE'列中,但收到上述错误。
看起来好像PK截断ZIPFILE的值以及SQL插入字符串中它后面的所有内容之后的特殊字符。如果我要通过使用PHPaddslashes()
函数来转义特殊字符,则可以完成插入,但是zip文件由于附加的斜杠而损坏。更改编码不是一种选择,因为我使用另一个应用程序从数据库下载数据,并且该应用程序要求值采用此编码。
有没有一种方法可以转义特殊字符而不损坏zip文件?
我包含一些代码以使事情更清晰。
应用程序使用Yii2框架
控制器代码
public function actionCreate()
{
$model = new Orders();
$model->load(Yii::$app->request->post())
//populates ZIPFILE property with binary value of the ASCII encoded ZIPFILE string(pre-populated) compressed to a .zip file and read using file_get_contents in the Zip model
$model->ZIPFILE = (new Zip)->asBinaryString($model->ZIPFILE);
if ($model->save()) {
return $this->redirect(['view', 'id' => $model->ID]);
} else {
return $this->render(
'create', [
'model' => $model,
]);
}
}
在邮编模型中
private string $_tempFolder = '/somecache/';
public function asBinaryString($content): ?string
{
$fileName = $this->create($content);
$fileAsBinary = file_get_contents(Yii::$app->basePath . $this->_tempFolder . $fileName);
return $fileAsBinary;
}
public function create($content): ?string
{
$zipName = \microtime();
try {
$zip = new \ZipArchive;
if ($zip->open(Yii::$app->basePath . $this->_tempFolder . $zipName, \ZipArchive::CREATE) === true) {
$zip->addFromString(time().'.RTF', $content);
$zip->close();
} else {
throw new Exception(Yii::t('app', 'Archive could not be created in cache folder.'));
}
} catch (\Throwable $th) {
throw $th;
}
return $zipName ?? null;
}
加载回$ model-> ZIPFILE的字符串如下所示:“PKa PM?ٟ1590409143。RTFu n 0 _e`Os R j * ƄA 5Dݨʻ@ 0 ...''
无法通过数据库中的链接将文件存储到磁盘上,因为这是对旧版应用程序的增强,该应用程序要求将数据以zip格式存储在数据库中。
尝试通过使用PHP bin2hex()将二进制zip转换为hex来接近解决方案,但未成功。十六进制没有特殊字符;因此,$ model保存得很好,但另一个应用程序无法读取保存到SQL Server的zip文件。
这不是一个简单的错字问题,已经尝试过在此处使用准备好的语句,但是不起作用。
在解决之前,我花了至少10天的时间在网上进行广泛的搜索并测试了各种解决方案。
上面问题的答案是不可能将二进制字符串直接保存到SQL Server数据库中。该文件需要作为hex
字符串发送。
解:
public function asBinary($content): ?string
{
$fileName = $this->create($content);
$fileAsBinary = file_get_contents(Yii::$app->cache->cachePath . '/' . $fileName);
return $fileAsBinary;
}
/**
* zips file in cache folder into archive
*/
public function create($content): ?string
{
$zipName = \microtime();
try {
$zip = new \ZipArchive;
if ($zip->open(Yii::$app->cache->cachePath . '/' . $zipName, \ZipArchive::CREATE) === true) {
$zip->addFromString(time().'.RTF', $content);
$zip->close();
} else {
throw new Exception(Yii::t('app', 'Archive could not be created in cache folder.'));
}
} catch (\Throwable $th) {
throw $th;
}
return $zipName ?? null;
}
//return file as Hex string
public function asHex($content): string
{
$fileAsBinary = $this->asBinary($content);
$unpackedBinaryFile = unpack('H*hex', $fileAsBinary);
$fileAsHex = '0x' . $unpackedBinaryFile['hex'];
return $fileAsHex;
}
在$ model中填充ZIPFILE
$model->ZIPFILE = (new Zip)->asHex($model->ZIPFILE);
压缩文件需要转换为hex
可以直接保存到SQL Server中的字符串。VARBINARY
当插入数据库时,SQL Server会将其转换为。
由于不清楚的原因,我无法使用Yii2的准备好的语句传递ZIPFILE。每次都会出错。另外,使用ActiveRecord的$model->save()
方法无法保存。必须使用SQL查询字符串插入。如果有人能说出原因,那就太好了。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句