讲师中心 微信公众号
AI工具推荐 视频效率加速

WordPress REST API 上传原始图片数据并避免空白媒体库问题

秋浩君_2535

秋浩君_2535

发布时间:2025-11-24 11:20:02

|

327人浏览过

|

来源于php中文网

原创

WordPress REST API 上传原始图片数据并避免空白媒体库问题

本教程详细指导如何通过wordpress rest api(v2)上传原始图片数据,而非文件路径或url。文章将深入分析常见上传失败(导致媒体库图片显示为空白)的原因,并提供一个基于curl的有效解决方案,确保图片正确上传并显示,同时包含关键代码示例和最佳实践。

理解WordPress REST API媒体上传机制

WordPress REST API v2的媒体上传端点(/wp/v2/media)设计用于接收文件数据。在处理图片上传时,API通常期望请求体直接包含图片的二进制原始数据,并依赖HTTP头信息(如Content-Type和Content-Disposition)来识别文件类型和文件名。

许多开发者在尝试上传原始图片数据时,常遇到的一个挑战是图片在WordPress媒体库中显示为空白。这通常是由于HTTP请求的构建方式不符合API的预期,尤其是在处理二进制数据时。

常见上传问题分析

考虑以下一种常见的、但可能导致问题的Guzzle请求构建方式:

if (isset($product['priority_web_image'])) {
    $image_name = $product['priority_web_image']['filename'];
    $data = $product['priority_web_image']['data']; // 假设这是原始图片数据,可能是base64编码
    $ext = substr($image_name, strpos($image_name, ".") + 1);
    if ($ext == 'jpg') {
        $ext = 'jpeg';
    }
    $mime_type = 'image/'.$ext;

    $headers = [
        'Authorization' => 'Bearer '.$result_auth->access_token,
        "cache-control" => "no-cache",
        "Content-Type"  =>  $mime_type, // 看起来正确
        "Content-Disposition" => "attachement;filename=".$image_name, // 看起来正确
    ];

    $body = [
        "source_url"  =>  $data, // 问题所在:将原始数据作为表单参数
        "slug"        =>  "image_test_pimcore",
        "status"      =>  "future",
        "title"       =>  $image_name,
        "media_type"  => "image",
        "mime_type"   =>  $mime_type
    ];

    $options = [
        "headers"      =>  $headers,
        "form_params"  =>  $body, // Guzzle会将此转换为x-www-form-urlencoded或multipart/form-data
    ];
    // ... 发送请求
}

上述代码的问题在于使用了form_params选项。当Guzzle使用form_params时,它会将$body数组中的键值对编码为application/x-www-form-urlencoded或multipart/form-data格式,并将其作为请求体发送。在这种情况下,$data(原始图片数据)被视为一个名为source_url的字符串参数,而不是请求体中的原始二进制文件内容。

WordPress API期望的是:

  1. 请求体直接包含图片文件的二进制数据。
  2. Content-Disposition头指定文件名。
  3. Content-Type头指定MIME类型。

将原始图片数据作为表单参数发送,会导致API无法正确解析上传的文件,从而在媒体库中创建空白条目。

解决方案:使用cURL进行二进制文件上传

正确的做法是将原始图片数据直接放入HTTP请求体中。以下是一个使用PHP的cURL库实现此功能的示例,它能够有效解决上述问题:

Full access to all Exchange 2010 EWS functions, should work with other EWS Open Source
Full access to all Exchange 2010 EWS functions, should work with other EWS Open Source

可完全访问 Exchange 2010 EWS,管理邮件、文件夹、附件、日历事件、联系人、任务及外出设置。

下载
<?php

/**
 * 上传原始图片数据到WordPress媒体库
 *
 * @param string $base64_data 图片的base64编码数据
 * @param string $image_name 原始文件名(包含扩展名)
 * @param string $access_token WordPress认证Bearer Token
 * @param string $wp_api_url WordPress站点API基础URL (e.g., 'https://your-wordpress-site.com')
 * @return object|null API响应对象或null
 */
function uploadImageToWordPress(string $base64_data, string $image_name, string $access_token, string $wp_api_url)
{
    // 1. 创建临时文件存储图片原始数据
    // 这是一个关键步骤,因为cURL通常需要从文件路径读取内容,
    // 或者直接将原始二进制数据作为POSTFIELDS。
    // 如果$base64_data已经是原始二进制,可以跳过base64_decode。
    // 这里假设$base64_data是base64编码的。
    $temp_dir = sys_get_temp_dir();
    $filepath = $temp_dir . '/' . uniqid('wp_image_') . '_' . $image_name;

    // 确保目录可写
    if (!is_writable($temp_dir)) {
        error_log("Temporary directory not writable: " . $temp_dir);
        return null;
    }

    // 将base64解码后的数据写入临时文件
    $decoded_data = base64_decode($base64_data);
    if ($decoded_data === false) {
        error_log("Failed to decode base64 data for image: " . $image_name);
        return null;
    }

    if (file_put_contents($filepath, $decoded_data) === false) {
        error_log("Failed to write image data to temporary file: " . $filepath);
        return null;
    }

    // 确保临时文件存在
    if (!file_exists($filepath)) {
        error_log("Temporary image file does not exist after creation: " . $filepath);
        return null;
    }

    // 2. 读取文件内容以准备上传
    $file_content = file_get_contents($filepath);
    if ($file_content === false) {
        error_log("Failed to read content from temporary file: " . $filepath);
        // 清理临时文件
        unlink($filepath);
        return null;
    }

    // 3. 构建cURL请求
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 返回响应内容而不是直接输出
    curl_setopt($ch, CURLOPT_URL, $wp_api_url . '/wp-json/wp/v2/media/'); // WordPress媒体API端点
    curl_setopt($ch, CURLOPT_POST, 1); // 设置为POST请求
    curl_setopt($ch, CURLOPT_POSTFIELDS, $file_content); // 关键:直接将文件内容作为请求体

    // 设置HTTP头
    // Content-Disposition 头是必须的,用于告知API文件名
    // Authorization 头用于认证
    // Content-Type 头可以根据文件扩展名自动推断,或者明确指定
    $headers = [
        "Content-Disposition: attachment; filename=\"$image_name\"",
        'Authorization: Bearer ' . $access_token,
        // 如果需要,可以明确设置Content-Type,例如:
        // "Content-Type: " . mime_content_type($filepath),
    ];
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

    // 4. 执行cURL请求并处理响应
    $result = curl_exec($ch);
    $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);

    if (curl_errno($ch)) {
        error_log('cURL Error: ' . curl_error($ch));
        $api_response = null;
    } else {
        $api_response = json_decode($result);
        if ($http_code >= 400) {
            error_log("WordPress API Error (HTTP $http_code): " . ($result ?? 'No response body'));
            // 可以进一步解析$api_response来获取详细错误信息
        }
    }

    curl_close($ch);

    // 5. 清理临时文件
    unlink($filepath);

    return $api_response;
}

// 示例用法:
// $product_image_data = [
//     'filename' => 'my_product_image.jpg',
//     'data' => 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=' // 示例base64编码的1x1像素透明GIF
// ];
// $auth_token = 'YOUR_BEARER_TOKEN';
// $wp_site_url = 'https://your-wordpress-site.com';

// if (isset($product_image_data)) {
//     $image_name_to_upload = $product_image_data['filename'];
//     $raw_image_data_base64 = $product_image_data['data'];

//     $response = uploadImageToWordPress($raw_image_data_base64, $image_name_to_upload, $auth_token, $wp_site_url);

//     if ($response && isset($response->id)) {
//         echo "图片上传成功!媒体ID: " . $response->id . "\n";
//         echo "图片URL: " . $response->source_url . "\n";
//     } else {
//         echo "图片上传失败。\n";
//         print_r($response);
//     }
// }
?>

关键步骤解析与注意事项

  1. 临时文件处理

    • 解码数据: 如果原始图片数据是Base64编码的字符串(如示例中的$product['priority_web_image']['data']),则必须先使用base64_decode()将其解码为二进制数据。
    • 写入临时文件: 将解码后的二进制数据写入一个临时文件。这一步是必要的,因为它简化了cURL的CURLOPT_POSTFIELDS选项的使用,使其可以直接读取文件内容。
    • 清理: 上传完成后,务必使用unlink()删除临时文件,以避免服务器磁盘空间被不必要的临时文件占用。
    • 替代方案: 如果你的原始数据已经是二进制字符串,并且你不想创建临时文件,你可以直接将二进制字符串传递给CURLOPT_POSTFIELDS。但请注意,对于非常大的文件,直接在内存中处理可能会消耗大量内存。
  2. cURL请求构建

    • CURLOPT_POSTFIELDS, $file_content:这是核心。它指示cURL将$file_content(即图片的二进制数据)作为整个请求体发送。这与form_params或multipart/form-data不同,后者会将数据封装在键值对中。
    • Content-Disposition头:必须包含filename属性,WordPress API会使用它来确定媒体文件的名称。格式应为attachment; filename="your_image_name.jpg"。
    • Authorization头:用于身份验证,通常是Bearer Token。
    • Content-Type头:虽然在某些情况下cURL可以根据CURLOPT_POSTFIELDS的内容自动推断,但显式设置(例如image/jpeg或image/png)是一个好习惯,可以提高兼容性和明确性。
  3. 错误处理

    • 检查file_put_contents和file_get_contents的返回值,确保文件操作成功。
    • 检查curl_exec的返回值和curl_errno,捕获cURL层面的错误。
    • 检查API响应的HTTP状态码(curl_getinfo($ch, CURLINFO_HTTP_CODE)),判断WordPress API是否成功处理了请求。通常2xx表示成功,4xx/5xx表示错误。
    • 解析API响应(json_decode($result)),WordPress会在错误时返回包含详细信息的JSON对象。

Guzzle HTTP客户端的等效实现

如果你更倾向于使用Guzzle,实现相同功能的关键在于使用body选项直接发送二进制数据,并正确设置headers:

<?php
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;

/**
 * 使用Guzzle上传原始图片数据到WordPress媒体库
 *
 * @param string $base64_data 图片的base64编码数据
 * @param string $image_name 原始文件名(包含扩展名)
 * @param string $access_token WordPress认证Bearer Token
 * @param string $wp_api_url WordPress站点API基础URL (e.g., 'https://your-wordpress-site.com')
 * @return object|null API响应对象或null
 */
function uploadImageWithGuzzle(string $base64_data, string $image_name, string $access_token, string $wp_api_url)
{
    $client = new Client();
    $temp_dir = sys_get_temp_dir();
    $filepath = $temp_dir . '/' . uniqid('wp_image_') . '_' . $image_name;

    $decoded_data = base64_decode($base64_data);
    if ($decoded_data === false || file_put_contents($filepath, $decoded_data) === false) {
        error_log("Failed to prepare image data for Guzzle upload: " . $image_name);
        return null;
    }

    try {
        $response = $client->request('POST', $wp_api_url . '/wp-json/wp/v2/media/', [
            'headers' => [
                'Authorization'     => 'Bearer ' . $access_token,
                'Content-Disposition' => 'attachment; filename="' . $image_name . '"',
                // Guzzle通常会根据'body'的内容自动设置Content-Type,
                // 但如果需要明确,可以添加 'Content-Type' => mime_content_type($filepath),
            ],
            'body' => fopen($filepath, 'r'), // 关键:使用fopen将文件流作为请求体
            // 或者直接使用字符串:'body' => $decoded_data, 但对于大文件不推荐
        ]);

        $api_response = json_decode($response->getBody()->getContents());
        return $api_response;

    } catch (RequestException $e) {
        error_log("Guzzle Request Error: " . $e->getMessage());
        if ($e->hasResponse()) {
            error_log("Guzzle Response: " . $e->getResponse()->getBody()->getContents());
        }
        return null;
    } finally {
        // 清理临时文件
        if (file_exists($filepath)) {
            unlink($filepath);
        }
    }
}

// 示例用法与cURL类似
// require 'vendor/autoload.php'; // 如果使用Composer
// $product_image_data = [
//     'filename' => 'guzzle_test_image.jpg',
//     'data' => 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII='
// ];
// $auth_token = 'YOUR_BEARER_TOKEN';
// $wp_site_url = 'https://your-wordpress-site.com';

// if (isset($product_image_data)) {
//     $image_name_to_upload = $product_image_data['filename'];
//     $raw_image_data_base64 = $product_image_data['data'];

//     $response = uploadImageWithGuzzle($raw_image_data_base64, $image_name_to_upload, $auth_token, $wp_site_url);

//     if ($response && isset($response->id)) {
//         echo "Guzzle 图片上传成功!媒体ID: " . $response->id . "\n";
//         echo "Guzzle 图片URL: " . $response->source_url . "\n";
//     } else {
//         echo "Guzzle 图片上传失败。\n";
//         print_r($response);
//     }
// }
?>

在Guzzle中,'body' => fopen($filepath, 'r') 是推荐的方式,它允许Guzzle以流式方式发送文件内容,对于大文件更高效。

总结

通过WordPress REST API上传原始图片数据时,核心在于理解API期望请求体直接包含二进制文件内容,而非将其作为表单参数。无论是使用cURL还是Guzzle,关键步骤都包括:将原始数据解码为二进制(如果需要)、将二进制数据作为请求体发送、并设置正确的Content-Disposition和Authorization等HTTP头。通过遵循这些指导原则,可以有效避免图片在WordPress媒体库中显示为空白的问题,确保媒体文件正确上传和管理。

热门AI工具

更多
DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

立刻MV
立刻MV Hot

立刻MV是一款AI文本写作工具,AI 音乐视频(MV)创作工具。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

Laper
Laper Hot

Laper是专为编剧、导演和制片人推出的 AI 原生剧本创作工具。

超级简历WonderCV

一款AI办公效率工具,主要用于免费求职简历模版下载制作,应届生职场人必备简历制作神器,适合需要提升相关任务效率的用户。

UpDream
UpDream Hot

一款AI视频创作工具,主要用于哔哩哔哩推出的自研AI视频创作工具,适合需要提升相关任务效率的用户。

蛙蛙写作

一款AI论文写作工具,主要用于超级AI智能写作助手,适合需要提升相关任务效率的用户。

Atoms
Atoms Hot

Atoms是一款AI智能体工具,第一支自动构建真实业务的 AI 团队。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

相关专题

更多
json数据格式
json数据格式

JSON是一种轻量级的数据交换格式。本专题为大家带来json数据格式相关文章,帮助大家解决问题。

1955

2023.08.07

json是什么
json是什么

JSON是一种轻量级的数据交换格式,具有简洁、易读、跨平台和语言的特点,JSON数据是通过键值对的方式进行组织,其中键是字符串,值可以是字符串、数值、布尔值、数组、对象或者null,在Web开发、数据交换和配置文件等方面得到广泛应用。本专题为大家提供json相关的文章、下载、课程内容,供大家免费下载体验。

2582

2023.08.23

jquery怎么操作json
jquery怎么操作json

操作的方法有:1、“$.parseJSON(jsonString)”2、“$.getJSON(url, data, success)”;3、“$.each(obj, callback)”;4、“$.ajax()”。更多jquery怎么操作json的详细内容,可以访问本专题下面的文章。

896

2023.10.13

go语言处理json数据方法
go语言处理json数据方法

本专题整合了go语言中处理json数据方法,阅读专题下面的文章了解更多详细内容。

2879

2025.09.10

curl_exec
curl_exec

curl_exec函数是PHP cURL函数列表中的一种,它的功能是执行一个cURL会话。给大家总结了一下php curl_exec函数的一些用法实例,这个函数应该在初始化一个cURL会话并且全部的选项都被设置后被调用。他的返回值成功时返回TRUE, 或者在失败时返回FALSE。

3323

2023.06.14

linux常见下载安装工具
linux常见下载安装工具

linux常见下载安装工具有APT、YUM、DNF、Snapcraft、Flatpak、AppImage、Wget、Curl等。想了解更多linux常见下载安装工具相关内容,可以阅读本专题下面的文章。

695

2023.10.30

登录token无效
登录token无效

登录token无效解决方法:1、检查token的有效期限,如果token已经过期,需要重新获取一个新的token;2、检查token的签名,如果签名不正确,需要重新获取一个新的token;3、检查密钥的正确性,如果密钥不正确,需要重新获取一个新的token;4、使用HTTPS协议传输token,建议使用HTTPS协议进行传输 ;5、使用双因素认证,双因素认证可以提高账户的安全性。

11766

2023.09.14

登录token无效怎么办
登录token无效怎么办

登录token无效的解决办法有检查Token是否过期、检查Token是否正确、检查Token是否被篡改、检查Token是否与用户匹配、清除缓存或Cookie、检查网络连接和服务器状态、重新登录或请求新的Token、联系技术支持或开发人员等。本专题为大家提供token相关的文章、下载、课程内容,供大家免费下载体验。

1425

2023.09.14

Vibeknow在线使用入口合集
Vibeknow在线使用入口合集

本专题汇总了Vibeknow在线创作视频的官方入口及网页版使用教程,涵盖PPT、PDF、Word等文档一键转讲解视频的核心操作,并整理了免费版水印规则与手机端浏览器访问指南,助你快速将知识内容视频化。

0

2026.09.21

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
墨刀帮助中心
墨刀帮助中心

共0课时 | 0人学习

MyEclipse学习中心
MyEclipse学习中心

共0课时 | 0人学习

Apache Subversion 官方手册
Apache Subversion 官方手册

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn