Sharepoint Rest API php curl post 与 docx 文件问题

Sharepoint Rest API php curl post with docx file issue

有与此类似的问题,但我没有发现任何与我的问题直接相关的问题。我对 PHP 和 curl 有点陌生,所以请多多包涵并提前致谢。

说明: 我有一个 php 应用程序正在将文件上传到 Sharepoint 2019 rest api。到目前为止,它适用于所有文件类型,但 .doc 和 .docx 格式文件除外。这些文件已成功发布,但一旦下载并打开,我就会收到如下错误:

“Word 在 {filename}.docx 中发现不可读的内容”。您要恢复此文档的内容吗?如果您信任此文档的来源,请单击“是”。

如果我单击“是”,文件将毫无问题地打开。如果我直接从 Sharepoint 站点下载文件,也会出现同样的问题。如何使用 curl 将 docx 文件传递​​给 rest api?似乎存在一些编码问题,但我不确定如何判断它在哪一边,因为 Sharepoint 告诉我的上传没有任何问题。我在 stack overflow 上发现的另一篇文章将数据分开,但那是 docusign rest api 并且是从 2013 年开始的。发现 Here。我是否也需要分解通话数据?

下面是我的文件上传代码

$files = $_FILES;
$local_file = $_FILES['input_document_upload'];

$fileName = $local_file['name'];
//I am assuming there is something with the encoding for curl_file_create below I am missing
$data = array(
    'uploaded_file' => curl_file_create($local_file['tmp_name'], $local_file['type'], $fileName)
);

$client_upload_url =  //ends in _api/web/lists/getbytitle('{documentFolder}')/rootfolder/files/add
$client_upload_url .= "(url='". $fileName ."',overwrite=true)";

$curl = curl_init();

curl_setopt_array($curl, array(
  CURLOPT_URL => $client_upload_url,//<-- no problem here since it uploads correctly 99% of the time
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => "",
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 30,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_NONE ,
  CURLOPT_POSTFIELDS=> $data,
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_HTTPHEADER => array(
    "Accept: application/json;odata=verbose",
    "cache-control: no-cache",
    "X-RequestDigest: " . $digest_value,
    //hardcoded the below type, but I have used several different content-type settings to try to get this working
//multipart/form-data
//application/octet-stream
    "Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document",
    "Authorization: //redacted
     ),
    ));
 
    $response = curl_exec($curl);


感谢您抽出宝贵时间!

经过大量实验和搜索,我找到了这个问题的答案。最大的罪魁祸首确实是内容类型。如果您使用以下代码:

$data = array(
    'uploaded_file' => curl_file_create($local_file['tmp_name'], $local_file['type'], $fileName)
);
/// redacted for space
 CURLOPT_POSTFIELDS=> $data,

curl 将自动删除您提供的任何 content-type 并提供自己的。你得到以下 headers:

Content-Type: multipart/form-data; boundary=----------637571310612295910
Content-Length: 12184

------------637571310612295910
Content-Disposition: form-data; name="uploaded_file"; filename="{filename}.docx"
Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document

Sharepoint 根本不喜欢这样。所以,你需要发送二进制数据,而不是 multipart/form-data。这可以像这样实现:

$uploadFile = file_get_contents($local_file['tmp_name']);
$curl = curl_init();

            curl_setopt_array($curl, array(
              CURLOPT_URL => $client_upload_url,
              CURLOPT_RETURNTRANSFER => true,
              CURLOPT_ENCODING => "",
              CURLOPT_MAXREDIRS => 10,
              CURLOPT_TIMEOUT => 30,
              CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_NONE ,
              CURLOPT_CUSTOMREQUEST => "POST",
            CURLOPT_POSTFIELDS=> $uploadFile, //<-- where the magic happens

              CURLOPT_HTTPHEADER => array(
                "Accept: application/json;odata=verbose",
                "cache-control: no-cache",
                "X-RequestDigest: " . $digest_value,
                "Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document",//

                "Authorization: {values}
              ),
            ));
 

这将为您带来如下结果

Accept: application/json; odata=verbose
Cache-Control: no-cache
X-RequestDigest:{redacted}
Authorization: {redacted}
Connection: Keep-Alive
Request-Id: |1bf3eca4-45702011fc30c20b.2.
Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document
Content-Length: 11947

{raw body here, not multipart/formdata}

这个故事的寓意是 file_get_contents 将为您提供字符串形式的二进制数据。您可以直接将其转储到 CURLOPT_POSTFIELDS.

这件事的灵感来自于 2008 年 post found here