|
|
@@ -271,40 +271,80 @@ class AIImageGenerationService
|
|
|
// 根据是否有参考图选择不同的请求方式
|
|
|
if ($isEditMode) {
|
|
|
// 使用原生 cURL 处理 multipart/form-data 格式
|
|
|
- $imageUrl = is_array($task->ref_img_url) ? $task->ref_img_url[0] : $task->ref_img_url;
|
|
|
+ $imageUrls = is_array($task->ref_img_url) ? $task->ref_img_url : [$task->ref_img_url];
|
|
|
|
|
|
- dLog('generate')->info('下载参考图片', ['image_url' => $imageUrl]);
|
|
|
+ // 限制最多4张参考图
|
|
|
+ $imageUrls = array_slice($imageUrls, 0, 4);
|
|
|
|
|
|
- // 下载图片内容
|
|
|
- $imageContent = @file_get_contents($imageUrl);
|
|
|
- if ($imageContent === false) {
|
|
|
- throw new \Exception('下载参考图片失败: ' . $imageUrl);
|
|
|
- }
|
|
|
-
|
|
|
- dLog('generate')->info('参考图片下载完成', ['size' => strlen($imageContent)]);
|
|
|
+ dLog('generate')->info('下载参考图片', ['image_urls' => $imageUrls, 'count' => count($imageUrls)]);
|
|
|
|
|
|
- // 保存为临时文件(cURL 需要真实文件路径)
|
|
|
- $extension = pathinfo(parse_url($imageUrl, PHP_URL_PATH), PATHINFO_EXTENSION) ?: 'png';
|
|
|
- $tempFile = tempnam(sys_get_temp_dir(), 'gpt_img_') . '.' . $extension;
|
|
|
- file_put_contents($tempFile, $imageContent);
|
|
|
+ // 下载所有参考图片并保存为临时文件
|
|
|
+ $tempFiles = [];
|
|
|
+ foreach ($imageUrls as $index => $imageUrl) {
|
|
|
+ $imageContent = @file_get_contents($imageUrl);
|
|
|
+ if ($imageContent === false) {
|
|
|
+ dLog('generate')->warning('下载参考图片失败,跳过', ['image_url' => $imageUrl]);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ dLog('generate')->info('参考图片下载完成', ['index' => $index, 'size' => strlen($imageContent)]);
|
|
|
+
|
|
|
+ // 保存为临时文件(cURL 需要真实文件路径)
|
|
|
+ $extension = pathinfo(parse_url($imageUrl, PHP_URL_PATH), PATHINFO_EXTENSION) ?: 'png';
|
|
|
+ $tempFile = tempnam(sys_get_temp_dir(), 'gpt_img_') . '.' . $extension;
|
|
|
+ file_put_contents($tempFile, $imageContent);
|
|
|
+
|
|
|
+ $tempFiles[] = [
|
|
|
+ 'path' => $tempFile,
|
|
|
+ 'extension' => $extension
|
|
|
+ ];
|
|
|
+
|
|
|
+ dLog('generate')->info('临时文件创建成功', ['file' => $tempFile, 'size' => filesize($tempFile)]);
|
|
|
+ }
|
|
|
|
|
|
- dLog('generate')->info('临时文件创建成功', ['file' => $tempFile, 'size' => filesize($tempFile)]);
|
|
|
+ if (empty($tempFiles)) {
|
|
|
+ throw new \Exception('所有参考图片下载失败');
|
|
|
+ }
|
|
|
|
|
|
// 构建 POST 字段
|
|
|
$postFields = [
|
|
|
- 'image' => new \CURLFile($tempFile, 'image/' . $extension, 'image.' . $extension),
|
|
|
'prompt' => $task->prompt,
|
|
|
'model' => 'gpt-image-2',
|
|
|
- 'n' => (int)$task->image_num,
|
|
|
+ 'n' => (string)$task->image_num, // 新接口要求字符串类型
|
|
|
+ 'response_format' => 'b64_json', // 新接口必填参数
|
|
|
];
|
|
|
|
|
|
- // 尺寸参数
|
|
|
+ // 尺寸参数(必填)
|
|
|
if ($task->width && $task->height) {
|
|
|
$postFields['size'] = $task->width . 'x' . $task->height;
|
|
|
+ } else {
|
|
|
+ $postFields['size'] = '1024x1024'; // 默认尺寸
|
|
|
}
|
|
|
|
|
|
- dLog('generate')->info('GPT-Image2 API参数(编辑模式-cURL)', ['api_url' => $api_url, 'prompt' => $task->prompt, 'size' => ($task->width . 'x' . $task->height), 'n' => (int)$task->image_num]);
|
|
|
- logDB('generate', 'info', 'GPT-Image2任务提交(编辑模式)', ['task_id' => $task->task_id, 'api_url' => $api_url, 'image_url' => $imageUrl, 'prompt' => $task->prompt]);
|
|
|
+ // 添加参考图片文件(支持多图,新接口要求使用 image 字段名)
|
|
|
+ foreach ($tempFiles as $index => $tempFile) {
|
|
|
+ $fieldName = 'image'; // 新接口统一使用 image 字段名
|
|
|
+ $postFields[$fieldName] = new \CURLFile(
|
|
|
+ $tempFile['path'],
|
|
|
+ 'image/' . $tempFile['extension'],
|
|
|
+ 'image' . ($index + 1) . '.' . $tempFile['extension']
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ dLog('generate')->info('GPT-Image2 API参数(编辑模式-cURL)', [
|
|
|
+ 'api_url' => $api_url,
|
|
|
+ 'prompt' => $task->prompt,
|
|
|
+ 'size' => $postFields['size'],
|
|
|
+ 'n' => $postFields['n'],
|
|
|
+ 'response_format' => $postFields['response_format'],
|
|
|
+ 'image_count' => count($tempFiles)
|
|
|
+ ]);
|
|
|
+ logDB('generate', 'info', 'GPT-Image2任务提交(编辑模式)', [
|
|
|
+ 'task_id' => $task->task_id,
|
|
|
+ 'api_url' => $api_url,
|
|
|
+ 'image_urls' => $imageUrls,
|
|
|
+ 'prompt' => $task->prompt
|
|
|
+ ]);
|
|
|
|
|
|
$startTime = microtime(true);
|
|
|
|
|
|
@@ -335,8 +375,10 @@ class AIImageGenerationService
|
|
|
$curlErrno = curl_errno($ch);
|
|
|
curl_close($ch);
|
|
|
|
|
|
- // 删除临时文件
|
|
|
- @unlink($tempFile);
|
|
|
+ // 删除所有临时文件
|
|
|
+ foreach ($tempFiles as $tempFile) {
|
|
|
+ @unlink($tempFile['path']);
|
|
|
+ }
|
|
|
|
|
|
$elapsed = round(microtime(true) - $startTime, 2);
|
|
|
dLog('generate')->info('cURL请求完成', ['elapsed' => $elapsed . 's', 'http_code' => $statusCode, 'curl_errno' => $curlErrno]);
|