如何不先保存到public文件夹直接将文件上传至Cloudinary
问题
希望在控制器中直接生成XML文件并上传至Cloudinary,无需先保存到本地public文件夹。当前代码用saveXML()先存本地再上传,尝试直接传SimpleXMLElement对象时报错:缺少必填参数 - file。
当前控制器代码:
public function fatturaxml($id) { $xml = new SimpleXMLElement('<?xml version="1.0" encoding="utf-8"?><mydoc></mydoc>'); $xml->addAttribute('version', '1.0'); $xml->addChild('datetime', date('Y-m-d H:i:s')); $person = $xml->addChild('person'); $person->addChild('firstname', 'Mkenny'); $person->addChild('secondname', 'Mary'); $person->addChild('telephone', '000000000'); $person->addChild('email', 'marymkenny@yahoo.com'); $xml->saveXML('myxml.xml'); $response = Response::make($xml->asXML(), 200); $response->header('Cache-Control', 'public'); $response->header('Content-Description', 'File Transfer'); $response->header('Content-Disposition', 'attachment; filename=test.xml'); $response->header('Content-Transfer-Encoding', 'binary'); $response->header('Content-Type', 'text/xml'); cloudinary()->uploadFile('myxml.xml', ['folder' => 'FolderTest',])->getSecurePath(); }
尝试的错误代码:
cloudinary()->uploadFile($xml, ['folder' => 'FolderTest',])->getSecurePath();
错误提示:缺少必填参数 - file
解决方案
完全可以实现不存本地直接上传,问题出在uploadFile()不接受SimpleXMLElement对象,它需要文件路径、资源流或者Base64编码字符串这类格式。给你两种可行的实现方式:
方法一:Base64编码XML字符串上传
把XML内容转成字符串后做Base64编码,用data: URI格式传给Cloudinary:
public function fatturaxml($id) { $xml = new SimpleXMLElement('<?xml version="1.0" encoding="utf-8"?><mydoc></mydoc>'); $xml->addAttribute('version', '1.0'); $xml->addChild('datetime', date('Y-m-d H:i:s')); $person = $xml->addChild('person'); $person->addChild('firstname', 'Mkenny'); $person->addChild('secondname', 'Mary'); $person->addChild('telephone', '000000000'); $person->addChild('email', 'marymkenny@yahoo.com'); // 生成XML字符串内容 $xmlContent = $xml->asXML(); // 转成Cloudinary支持的data URI格式 $base64Xml = 'data:text/xml;base64,' . base64_encode($xmlContent); // 直接上传到Cloudinary $uploadResult = cloudinary()->uploadFile($base64Xml, [ 'folder' => 'FolderTest', 'public_id' => 'test_xml' // 可选,自定义文件名,不填会自动生成随机名 ])->getSecurePath(); // 生成下载响应 $response = Response::make($xmlContent, 200); $response->header('Cache-Control', 'public'); $response->header('Content-Description', 'File Transfer'); $response->header('Content-Disposition', 'attachment; filename=test.xml'); $response->header('Content-Transfer-Encoding', 'binary'); $response->header('Content-Type', 'text/xml'); return $response; }
方法二:临时内存流上传
把XML字符串写入PHP临时内存流,再将流对象传给Cloudinary:
public function fatturaxml($id) { $xml = new SimpleXMLElement('<?xml version="1.0" encoding="utf-8"?><mydoc></mydoc>'); $xml->addAttribute('version', '1.0'); $xml->addChild('datetime', date('Y-m-d H:i:s')); $person = $xml->addChild('person'); $person->addChild('firstname', 'Mkenny'); $person->addChild('secondname', 'Mary'); $person->addChild('telephone', '000000000'); $person->addChild('email', 'marymkenny@yahoo.com'); $xmlContent = $xml->asXML(); // 创建临时内存流 $tempStream = fopen('php://temp', 'r+'); fwrite($tempStream, $xmlContent); rewind($tempStream); // 将指针移到流的开头位置 // 上传流到Cloudinary $uploadResult = cloudinary()->uploadFile($tempStream, [ 'folder' => 'FolderTest', 'public_id' => 'test_xml' ])->getSecurePath(); fclose($tempStream); // 用完记得关闭临时流 // 生成下载响应 $response = Response::make($xmlContent, 200); $response->header('Cache-Control', 'public'); $response->header('Content-Description', 'File Transfer'); $response->header('Content-Disposition', 'attachment; filename=test.xml'); $response->header('Content-Transfer-Encoding', 'binary'); $response->header('Content-Type', 'text/xml'); return $response; }
关键说明
- 两种方法都不需要调用
saveXML()存本地,直接用asXML()获取XML字符串在内存中处理。 - Cloudinary的
uploadFile()支持多种输入类型,只要把XML内容转换成它能识别的格式就行,不用绕本地文件这一步。
内容的提问来源于stack exchange,提问作者Sarah
相关产品推荐
相关产品推荐

