You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决PHP+OAuth2上传SharePoint时的ID3035格式错误?

排查SharePoint文件上传时的「ID3035: The request was not valid or is malformed.」错误

以下是针对你的代码和错误的具体排查点及修复方案:

1. 文档库名称的URL编码问题

你的文档库名称「Plan de Trabajo」包含空格,直接拼接在API URL中会触发格式错误。需要对文档库名称进行URL编码后再传入getbytitle方法。

2. 文件名与本地文件不匹配

代码中$file_name设置为mi-archivo.pdf,但实际上传的本地文件是Azul.jpg,虽然这不是ID3035的直接原因,但会导致上传后文件类型混乱,建议保持两者一致。

3. Content-Length计算不准确

使用strlen($file_content)统计二进制文件长度可能出错,因为strlen按字符数计算,而二进制文件应使用filesize($file_path)获取准确字节大小。

4. 缺少必要的请求头

SharePoint REST API需要明确指定Accept: application/json头,否则可能返回非预期响应格式,导致请求被判定为无效。

5. 凭据变量的多余空格

你的client_id和client_secret变量末尾带有空格,会导致认证失败,需去掉这些空格。


修改后的完整代码

// SharePoint站点URL
$site_url = 'https://usbbogedu.sharepoint.com/vacademica';

// 文档库名称
$library_name = 'Plan de Trabajo';
// 对含空格的文档库名称进行URL编码
$encoded_library_name = rawurlencode($library_name);

// 上传后的文件名(与本地文件保持一致)
$file_name = 'Azul.jpg';

// 本地文件路径
$file_path = '../subida_sp/Azul.jpg';

// OAuth2认证信息
$client_id = 'client_id'; // 去掉末尾空格
$client_secret = 'client_secret'; // 去掉末尾空格
$tenant_id = 'tenant_id';
$resource = 'https://usbbogedu.sharepoint.com';

// 获取OAuth2访问令牌
$auth_url = "https://login.microsoftonline.com/$tenant_id/oauth2/token";
$ch = curl_init($auth_url);
$data = array(
    'grant_type' => 'client_credentials',
    'client_id' => $client_id,
    'client_secret' => $client_secret,
    'resource' => $resource
);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
if (false == $response) {
    echo "获取OAuth2令牌失败\n";
    die(curl_error($ch));
}
$token_data = json_decode($response, true);
// 增加令牌获取失败的判断
if (!isset($token_data['access_token'])) {
    echo "令牌获取失败: " . $response . "\n";
    die();
}
$token = $token_data['access_token'];

// SharePoint API请求URL(使用编码后的文档库名称)
$url = $site_url . "/_api/web/lists/getbytitle('$encoded_library_name')/RootFolder/Files/add(url='$file_name',overwrite=true)";

// 读取本地文件内容
$file_content = file_get_contents($file_path);
if ($file_content === false) {
    echo "读取本地文件失败\n";
    die();
}

// 请求头设置
$headers = array(
    'Authorization: Bearer ' . $token,
    'Content-Type: application/octet-stream',
    'Content-Length: ' . filesize($file_path), // 使用filesize获取准确文件大小
    'Accept: application/json;odata=verbose' // 添加必要的Accept头
);

// 发送上传请求
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $file_content);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// 开启SSL验证(生产环境建议保持开启)
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);

$response = curl_exec($ch);
if (false == $response) {
    echo "上传请求失败\n";
    $info = curl_getinfo($ch);
    foreach($info as $key => $value){
        echo "$key: $value <br>";
    }
    echo "Curl错误信息: " . curl_error($ch) . "<br>";
}
else {
    echo "响应内容: ". $response ."\n";
    $data = json_decode($response);
    if (json_last_error() !== JSON_ERROR_NONE) {
        echo "响应不是有效JSON格式\n";
    }
}
curl_close($ch);

额外检查项

  • 确认Azure AD应用已被授予Sites.FullControl.All应用权限,并完成了管理员同意。
  • 验证$site_url指向的站点确实存在且可访问。
  • 检查本地文件路径是否正确,PHP进程是否有读取该文件的权限。

内容的提问来源于stack exchange,提问作者jaison dario bejarano valdes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 03:25:00