如何使用 PHP-Curl 将大文件上传到 Onedrive
How Upload large files to Onedrive using PHP-Curl
我需要将大于 4MB 的文件上传到 onedrive 帐户。我正在尝试 PHP 并为此卷曲。有没有人试过这个选项,请帮我解决这个问题。
$url='https://graph.microsoft.com/v1.0/me/drive/root:/filename:/createUploadSession';
$data= '{}';
$header = array('Content-Type: json',
"Cache-Control: no-cache",
"Pragma: no-cache",
"Authorization: bearer {Access Token}");
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header );
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
从结果中获取上传URL,
$graph_url = $result['uploadUrl'];
$fragSize = 320 * 1024;
$file = file_get_contents($filename_location);
$fileSize = strlen($file);
$numFragments = ceil($fileSize / $fragSize);
$bytesRemaining = $fileSize;
$i = 0;
$ch = curl_init($graph_url);
while ($i < $numFragments) {
$chunkSize = $numBytes = $fragSize;
$start = $i * $fragSize;
$end = $i * $fragSize + $chunkSize - 1;
$offset = $i * $fragSize;
if ($bytesRemaining < $chunkSize) {
$chunkSize = $numBytes = $bytesRemaining;
$end = $fileSize - 1;
}
if ($stream = fopen($filename_location, 'r')) {
// get contents using offset
$data = stream_get_contents($stream, $chunkSize, $offset);
fclose($stream);
}
$content_range = " bytes " . $start . "-" . $end . "/" . $fileSize;
$headers = array(
"Content-Length: $numBytes",
"Content-Range:$content_range"
);
curl_setopt($ch, CURLOPT_URL, $graph_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, constant('CURL_SSL_VERIFYPEER_STATUS'));
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$server_output = curl_exec($ch);
$info = curl_getinfo($ch);
$bytesRemaining = $bytesRemaining - $chunkSize;
$i++;
}
当你传递最后一组数据时,它应该是正确的数据字节。否则上传会话将失败。
您的申请需要:
- 创建上传session
- 上传字节到上传session
请参阅 OneDrive 开发中心的上传大文件并上传 session 文档页面:https://docs.microsoft.com/en-us/onedrive/developer/rest-api/api/driveitem_createuploadsession#create-an-upload-session 详细了解每个步骤的请求类型以及 JSON 或预期的 http 响应代码。
从 PHP 功能的角度来看,您需要:
- 确定上传文件的属性(文件大小、文件名)
- 通过 curl 发送 post 数据以创建上传 session(有关 #1 的示例代码片段,请参阅标题为 SEND POST FROM CURL in this blog post 的部分。)
- 将来自 JSON 响应的 uploadUrl 解析为 php 变量
- 通过 cURL 将二进制内容发送到上面提取的 uploadURL(请参阅标题为 Send the binary contents via cURL in this blog post 的部分(发送整个文件或部分块 - 应考虑文件大小和 connection/bandwidth确定方法)
- 解析响应 header(http 响应代码)并有条件地:
- 如果失败则使用预期的字节范围重试(HTTP 416 请求范围不可满足的响应代码)
- 如果传输字节 ranges/partials(
202 Accepted
的响应代码),则继续下一个字节范围 - 参考 "Resuming an in-progress upload"
- complete/return/exit 功能失效(
HTTP 200 OK
或 HTTP 201 Created
的响应代码)
- 在任何 50x 响应上,发送 GET 请求(参考 "Resuming an in-progress upload")以确定发送什么 next/how 以恢复
如果检测到文件名冲突(HTTP/1.1 409 Conflict
的响应代码):
- Send a DELETE request using curl command 取消上传 session(您应该得到
HTTP/1.1 204 No Content
. 的响应代码
- Resolve/handle名称冲突
- 重启进程
这段代码对我有用:
<?php
$fileName="myfile.zip";
$filename_location=realpath($fileName);
$token="{access token}";
$ch = curl_init();
$url="https://graph.microsoft.com/v1.0/me/drive/root:/api/$fileName:/createUploadSession";
curl_setopt($ch, CURLOPT_URL,$url );
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
$data= '{
"item": {
"@microsoft.graph.conflictBehavior": "rename",
"description": "description",
"fileSystemInfo": { "@odata.type": "microsoft.graph.fileSystemInfo" },
"name": "'.$fileName.'"
}
}';
$header = array(
'Content-Type: application/json',
"Cache-Control: no-cache",
"Pragma: no-cache",
"Authorization: bearer $token");
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header );
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
$result = json_decode(curl_exec($ch)) ;
$graph_url = $result->uploadUrl;
$fragSize = 320 * 1024;
$file = file_get_contents($filename_location);
$fileSize = strlen($file);
$numFragments = ceil($fileSize / $fragSize);
$bytesRemaining = $fileSize;
$i = 0;
$ch = curl_init($graph_url);
while ($i < $numFragments) {
$chunkSize = $numBytes = $fragSize;
$start = $i * $fragSize;
$end = $i * $fragSize + $chunkSize - 1;
$offset = $i * $fragSize;
if ($bytesRemaining < $chunkSize) {
$chunkSize = $numBytes = $bytesRemaining;
$end = $fileSize - 1;
}
if ($stream = fopen($filename_location, 'r')) {
// get contents using offset
$data = stream_get_contents($stream, $chunkSize, $offset);
fclose($stream);
}
$content_range = " bytes " . $start . "-" . $end . "/" . $fileSize;
$headers = array(
"Content-Length: $numBytes",
"Content-Range:$content_range"
);
curl_setopt($ch, CURLOPT_URL, $graph_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$server_output = curl_exec($ch);
$info = curl_getinfo($ch);
$bytesRemaining = $bytesRemaining - $chunkSize;
$i++;
}
?>
我需要将大于 4MB 的文件上传到 onedrive 帐户。我正在尝试 PHP 并为此卷曲。有没有人试过这个选项,请帮我解决这个问题。
$url='https://graph.microsoft.com/v1.0/me/drive/root:/filename:/createUploadSession';
$data= '{}';
$header = array('Content-Type: json',
"Cache-Control: no-cache",
"Pragma: no-cache",
"Authorization: bearer {Access Token}");
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header );
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
从结果中获取上传URL,
$graph_url = $result['uploadUrl'];
$fragSize = 320 * 1024;
$file = file_get_contents($filename_location);
$fileSize = strlen($file);
$numFragments = ceil($fileSize / $fragSize);
$bytesRemaining = $fileSize;
$i = 0;
$ch = curl_init($graph_url);
while ($i < $numFragments) {
$chunkSize = $numBytes = $fragSize;
$start = $i * $fragSize;
$end = $i * $fragSize + $chunkSize - 1;
$offset = $i * $fragSize;
if ($bytesRemaining < $chunkSize) {
$chunkSize = $numBytes = $bytesRemaining;
$end = $fileSize - 1;
}
if ($stream = fopen($filename_location, 'r')) {
// get contents using offset
$data = stream_get_contents($stream, $chunkSize, $offset);
fclose($stream);
}
$content_range = " bytes " . $start . "-" . $end . "/" . $fileSize;
$headers = array(
"Content-Length: $numBytes",
"Content-Range:$content_range"
);
curl_setopt($ch, CURLOPT_URL, $graph_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, constant('CURL_SSL_VERIFYPEER_STATUS'));
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$server_output = curl_exec($ch);
$info = curl_getinfo($ch);
$bytesRemaining = $bytesRemaining - $chunkSize;
$i++;
}
当你传递最后一组数据时,它应该是正确的数据字节。否则上传会话将失败。
您的申请需要:
- 创建上传session
- 上传字节到上传session
请参阅 OneDrive 开发中心的上传大文件并上传 session 文档页面:https://docs.microsoft.com/en-us/onedrive/developer/rest-api/api/driveitem_createuploadsession#create-an-upload-session 详细了解每个步骤的请求类型以及 JSON 或预期的 http 响应代码。
从 PHP 功能的角度来看,您需要:
- 确定上传文件的属性(文件大小、文件名)
- 通过 curl 发送 post 数据以创建上传 session(有关 #1 的示例代码片段,请参阅标题为 SEND POST FROM CURL in this blog post 的部分。)
- 将来自 JSON 响应的 uploadUrl 解析为 php 变量
- 通过 cURL 将二进制内容发送到上面提取的 uploadURL(请参阅标题为 Send the binary contents via cURL in this blog post 的部分(发送整个文件或部分块 - 应考虑文件大小和 connection/bandwidth确定方法)
- 解析响应 header(http 响应代码)并有条件地:
- 如果失败则使用预期的字节范围重试(HTTP 416 请求范围不可满足的响应代码)
- 如果传输字节 ranges/partials(
202 Accepted
的响应代码),则继续下一个字节范围 - 参考 "Resuming an in-progress upload" - complete/return/exit 功能失效(
HTTP 200 OK
或HTTP 201 Created
的响应代码) - 在任何 50x 响应上,发送 GET 请求(参考 "Resuming an in-progress upload")以确定发送什么 next/how 以恢复
如果检测到文件名冲突(HTTP/1.1 409 Conflict
的响应代码):
- Send a DELETE request using curl command 取消上传 session(您应该得到
HTTP/1.1 204 No Content
. 的响应代码
- Resolve/handle名称冲突
- 重启进程
这段代码对我有用:
<?php
$fileName="myfile.zip";
$filename_location=realpath($fileName);
$token="{access token}";
$ch = curl_init();
$url="https://graph.microsoft.com/v1.0/me/drive/root:/api/$fileName:/createUploadSession";
curl_setopt($ch, CURLOPT_URL,$url );
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
$data= '{
"item": {
"@microsoft.graph.conflictBehavior": "rename",
"description": "description",
"fileSystemInfo": { "@odata.type": "microsoft.graph.fileSystemInfo" },
"name": "'.$fileName.'"
}
}';
$header = array(
'Content-Type: application/json',
"Cache-Control: no-cache",
"Pragma: no-cache",
"Authorization: bearer $token");
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header );
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
$result = json_decode(curl_exec($ch)) ;
$graph_url = $result->uploadUrl;
$fragSize = 320 * 1024;
$file = file_get_contents($filename_location);
$fileSize = strlen($file);
$numFragments = ceil($fileSize / $fragSize);
$bytesRemaining = $fileSize;
$i = 0;
$ch = curl_init($graph_url);
while ($i < $numFragments) {
$chunkSize = $numBytes = $fragSize;
$start = $i * $fragSize;
$end = $i * $fragSize + $chunkSize - 1;
$offset = $i * $fragSize;
if ($bytesRemaining < $chunkSize) {
$chunkSize = $numBytes = $bytesRemaining;
$end = $fileSize - 1;
}
if ($stream = fopen($filename_location, 'r')) {
// get contents using offset
$data = stream_get_contents($stream, $chunkSize, $offset);
fclose($stream);
}
$content_range = " bytes " . $start . "-" . $end . "/" . $fileSize;
$headers = array(
"Content-Length: $numBytes",
"Content-Range:$content_range"
);
curl_setopt($ch, CURLOPT_URL, $graph_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$server_output = curl_exec($ch);
$info = curl_getinfo($ch);
$bytesRemaining = $bytesRemaining - $chunkSize;
$i++;
}
?>