diff --git a/app/common/service/WordpressSiteService.php b/app/common/service/WordpressSiteService.php index 89a2861..dee006f 100644 --- a/app/common/service/WordpressSiteService.php +++ b/app/common/service/WordpressSiteService.php @@ -999,6 +999,105 @@ class WordpressSiteService } } + /** + * 上传文件(PDF等附件)到 WordPress 媒体库 + * + * @param string $domain + * @param string $api_user + * @param string $api_secret + * @param string $fileUrl 文件URL + * @return array + * @throws \Exception + */ + public function uploadFileToWp(string $domain, string $api_user, string $api_secret, string $fileUrl): array + { + // 使用 OssService 生成完整的文件URL + $ossUrl = (new OssService)->generatePrivateUrl($fileUrl, 3600); + + $client = new Client(); + + // 从原始 URL 提取文件扩展名 + $pathInfo = pathinfo(parse_url($fileUrl, PHP_URL_PATH)); + $extension = strtolower($pathInfo['extension'] ?? 'pdf'); + $filename = ($pathInfo['filename'] ?? 'file') . '.' . $extension; + + // 确定Content-Type + $mimeTypes = [ + 'pdf' => 'application/pdf', + 'doc' => 'application/msword', + 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'xls' => 'application/vnd.ms-excel', + 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'zip' => 'application/zip', + 'rar' => 'application/x-rar-compressed', + ]; + $contentType = $mimeTypes[$extension] ?? 'application/octet-stream'; + + $mediaUrl = $domain . '/wp-json/wp/v2/media'; + + // 本地临时文件路径 + $tempDir = runtime_path('temp') . '/wp_files/'; + if (!is_dir($tempDir)) { + mkdir($tempDir, 0755, true); + } + $tempFilePath = $tempDir . md5($fileUrl) . '.' . $extension; + + try { + // 1. 下载文件到本地临时文件 + $fileContent = file_get_contents($ossUrl); + if ($fileContent === false) { + throw new \Exception('文件下载失败:' . $ossUrl); + } + + // 写入临时文件 + $bytesWritten = file_put_contents($tempFilePath, $fileContent); + if ($bytesWritten === false) { + throw new \Exception('写入临时文件失败:' . $tempFilePath); + } + + // 2. 使用 GuzzleHttp 上传本地文件到 WP 媒体库 + $fileHandle = fopen($tempFilePath, 'r'); + + $multipart = [ + [ + 'name' => 'file', + 'filename' => $filename, + 'contents' => $fileHandle, + 'headers' => [ + 'Content-Type' => $contentType, + ], + ], + ]; + + $response = $client->post($mediaUrl, [ + RequestOptions::AUTH => [$api_user, $api_secret], + RequestOptions::MULTIPART => $multipart, + RequestOptions::VERIFY => false, + RequestOptions::TIMEOUT => 60, + ]); + + // 关闭文件句柄 + if (is_resource($fileHandle)) { + fclose($fileHandle); + } + + $result = json_decode($response->getBody()->getContents(), true); + return $result; + + } catch (\Exception $e) { + Log::error('上传文件到WordPress失败', [ + 'file_url' => $fileUrl, + 'error' => $e->getMessage(), + ]); + throw new \Exception('上传文件失败:' . $e->getMessage()); + } finally { + // 3. 删除临时文件 + if (file_exists($tempFilePath)) { + @unlink($tempFilePath); + } + } + } + /** * 创建产品到新站点(使用 Gutenberg Blocks 结构) * @@ -1116,6 +1215,27 @@ class WordpressSiteService $data['pa_brand'] = [$brandId]; } + // 处理附件:上传第一个附件到WordPress,使用ACF字段存储 + if (!empty($car->attachment)) { + $attachments = json_decode($car->attachment, true); + if (is_array($attachments) && count($attachments) > 0) { + $firstAttachment = $attachments[0]; + $attachmentSrc = $firstAttachment['src'] ?? ''; + if (!empty($attachmentSrc)) { + try { + $uploadedFile = $this->uploadFileToWp($domain, $site->api_user, $site->api_secret, $attachmentSrc); + // ACF attachment字段直接存储媒体ID + $data['acf']['attachment'] = $uploadedFile['id']; + } catch (\Exception $e) { + Log::error('附件上传失败', [ + 'attachment_src' => $attachmentSrc, + 'error' => $e->getMessage(), + ]); + } + } + } + } + // 设置主图和车辆相册(ACF字段) if (!empty($uploadedImages)) { $allImageIds = array_map(function($img) {