通过 HTTP 将大文件上传到 Dropbox API
Upload large files to Dropbox via HTTP API
我目前正在实施一种将我的网络服务器上的文件上传到我的 Dropbox 应用程序目录的机制。
如 API 文档所述,/upload 端点 (https://www.dropbox.com/developers/documentation/http/documentation#files-upload) 接受最大 150MB 的文件。然而,我正在处理可能高达 2GB 大小的图像和视频。
因此我需要使用 upload_session 端点。有一个端点用于启动会话 (https://www.dropbox.com/developers/documentation/http/documentation#files-upload_session-start)、附加数据和完成会话。
我目前不清楚的是如何准确使用这些端点。我是否必须将服务器上的文件拆分为 150MB 的块(我如何处理视频文件?),然后使用 /start 上传第一个块,使用 /append 上传下一个块,使用 /finish 上传最后一个块?或者我可以只指定文件,然后 API 以某种方式 (??) 为我进行拆分吗?显然不是,但不知何故我无法理解我应该如何计算、拆分和存储块在我的网络服务器上并且不丢失其间的会话...
非常感谢任何建议或进一步的领先链接。谢谢!
正如 Greg 在评论中提到的,您决定如何管理 "chunks" 文件。除了他的 .NET 示例,Dropbox 在 JavaScript upload example of the Dropbox API v2 JavaScript SDK 中还有一个很好的上传会话实现。
在 high-level 处,您将文件拆分成更小的大小(又名 "chunks"),然后按特定顺序将它们传递给 upload_session 机制。上传机制有几个部分需要按以下顺序使用:
- 呼叫/files/upload_session/start。在以下方法中使用生成的
session_id
作为参数,以便 Dropbox 知道您正在与哪个会话交互。
将文件的每个 "chunk" 递增地传递给 /files/upload_session/append_v2。需要注意的几件事:
- 第一个调用将return一个
cursor
,用于以特定顺序遍历文件的块。它在每次连续调用此方法时作为参数传递(光标在每次响应时更新)。
- final 调用必须包含 属性
"close": true
,这会关闭会话以便上传。
将最终的 cursor
(和 commit
信息)传递给 /files/upload_session/finish。如果您在响应中看到新的文件元数据,那么 您做到了!!
- 如果您要上传许多 文件而不是大 文件,那么/files/upload_session/finish_batch and /files/upload_session/finish_batch/check 是最佳选择。
我知道这是一个旧的 post,但这里有一个功能齐全的解决方案来解决您的问题。也许其他人会发现它有用。 :)
<?php
$backup_folder = glob('/var/www/test_folder/*.{sql,gz,rar,zip}', GLOB_BRACE); // Accepted file types (sql,gz,rar,zip)
$token = '<ACCESS TOKEN>'; // Dropbox Access Token;
$append_url = 'https://content.dropboxapi.com/2/files/upload_session/append_v2';
$start_url = 'https://content.dropboxapi.com/2/files/upload_session/start';
$finish_url = 'https://content.dropboxapi.com/2/files/upload_session/finish';
if (!empty($backup_folder)) {
foreach ($backup_folder as $single_folder_file) {
$file_name= basename($single_folder_file); // File name
$destination_folder = 'destination_folder'; // Dropbox destination folder
$info_array = array();
$info_array["close"] = false;
$headers = array(
'Authorization: Bearer ' . $token,
'Content-Type: application/octet-stream',
'Dropbox-API-Arg: '.json_encode($info_array)
);
$chunk_size = 50000000; // 50mb
$fp = fopen($single_folder_file, 'rb');
$fileSize = filesize($single_folder_file); // File size
$tosend = $fileSize;
$first = $tosend > $chunk_size ? $chunk_size : $tosend;
$ch = curl_init($start_url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, fread($fp, $first));
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
$response = curl_exec($ch);
$tosend -= $first;
$resp = explode('"',$response);
$sesion = $resp[3];
$position = $first;
$info_array["cursor"] = array();
$info_array["cursor"]["session_id"] = $sesion;
while ($tosend > $chunk_size)
{
$info_array["cursor"]["offset"] = $position;
$headers[2] = 'Dropbox-API-Arg: '.json_encode($info_array);
curl_setopt($ch, CURLOPT_URL, $append_url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_POSTFIELDS, fread($fp, $chunk_size));
curl_exec($ch);
$tosend -= $chunk_size;
$position += $chunk_size;
}
unset($info_array["close"]);
$info_array["cursor"]["offset"] = $position;
$info_array["commit"] = array();
$info_array["commit"]["path"] = '/'. $destination_folder . '/' . $file_name;
$info_array["commit"]["mode"] = array();
$info_array["commit"]["mode"][".tag"] = "overwrite";
$info_array["commit"]["autorename"] = true;
$info_array["commit"]["mute"] = false;
$info_array["commit"]["strict_conflict"] = false;
$headers[2] = 'Dropbox-API-Arg: '. json_encode($info_array);
curl_setopt($ch, CURLOPT_URL, $finish_url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_POSTFIELDS, $tosend > 0 ? fread($fp, $tosend) : null);
curl_exec($ch);
curl_close($ch);
fclose($fp);
unlink($single_folder_file); // Remove files from server folder
}
}
我目前正在实施一种将我的网络服务器上的文件上传到我的 Dropbox 应用程序目录的机制。
如 API 文档所述,/upload 端点 (https://www.dropbox.com/developers/documentation/http/documentation#files-upload) 接受最大 150MB 的文件。然而,我正在处理可能高达 2GB 大小的图像和视频。
因此我需要使用 upload_session 端点。有一个端点用于启动会话 (https://www.dropbox.com/developers/documentation/http/documentation#files-upload_session-start)、附加数据和完成会话。
我目前不清楚的是如何准确使用这些端点。我是否必须将服务器上的文件拆分为 150MB 的块(我如何处理视频文件?),然后使用 /start 上传第一个块,使用 /append 上传下一个块,使用 /finish 上传最后一个块?或者我可以只指定文件,然后 API 以某种方式 (??) 为我进行拆分吗?显然不是,但不知何故我无法理解我应该如何计算、拆分和存储块在我的网络服务器上并且不丢失其间的会话...
非常感谢任何建议或进一步的领先链接。谢谢!
正如 Greg 在评论中提到的,您决定如何管理 "chunks" 文件。除了他的 .NET 示例,Dropbox 在 JavaScript upload example of the Dropbox API v2 JavaScript SDK 中还有一个很好的上传会话实现。
在 high-level 处,您将文件拆分成更小的大小(又名 "chunks"),然后按特定顺序将它们传递给 upload_session 机制。上传机制有几个部分需要按以下顺序使用:
- 呼叫/files/upload_session/start。在以下方法中使用生成的
session_id
作为参数,以便 Dropbox 知道您正在与哪个会话交互。 将文件的每个 "chunk" 递增地传递给 /files/upload_session/append_v2。需要注意的几件事:
- 第一个调用将return一个
cursor
,用于以特定顺序遍历文件的块。它在每次连续调用此方法时作为参数传递(光标在每次响应时更新)。 - final 调用必须包含 属性
"close": true
,这会关闭会话以便上传。
- 第一个调用将return一个
将最终的
cursor
(和commit
信息)传递给 /files/upload_session/finish。如果您在响应中看到新的文件元数据,那么 您做到了!!- 如果您要上传许多 文件而不是大 文件,那么/files/upload_session/finish_batch and /files/upload_session/finish_batch/check 是最佳选择。
我知道这是一个旧的 post,但这里有一个功能齐全的解决方案来解决您的问题。也许其他人会发现它有用。 :)
<?php
$backup_folder = glob('/var/www/test_folder/*.{sql,gz,rar,zip}', GLOB_BRACE); // Accepted file types (sql,gz,rar,zip)
$token = '<ACCESS TOKEN>'; // Dropbox Access Token;
$append_url = 'https://content.dropboxapi.com/2/files/upload_session/append_v2';
$start_url = 'https://content.dropboxapi.com/2/files/upload_session/start';
$finish_url = 'https://content.dropboxapi.com/2/files/upload_session/finish';
if (!empty($backup_folder)) {
foreach ($backup_folder as $single_folder_file) {
$file_name= basename($single_folder_file); // File name
$destination_folder = 'destination_folder'; // Dropbox destination folder
$info_array = array();
$info_array["close"] = false;
$headers = array(
'Authorization: Bearer ' . $token,
'Content-Type: application/octet-stream',
'Dropbox-API-Arg: '.json_encode($info_array)
);
$chunk_size = 50000000; // 50mb
$fp = fopen($single_folder_file, 'rb');
$fileSize = filesize($single_folder_file); // File size
$tosend = $fileSize;
$first = $tosend > $chunk_size ? $chunk_size : $tosend;
$ch = curl_init($start_url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, fread($fp, $first));
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
$response = curl_exec($ch);
$tosend -= $first;
$resp = explode('"',$response);
$sesion = $resp[3];
$position = $first;
$info_array["cursor"] = array();
$info_array["cursor"]["session_id"] = $sesion;
while ($tosend > $chunk_size)
{
$info_array["cursor"]["offset"] = $position;
$headers[2] = 'Dropbox-API-Arg: '.json_encode($info_array);
curl_setopt($ch, CURLOPT_URL, $append_url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_POSTFIELDS, fread($fp, $chunk_size));
curl_exec($ch);
$tosend -= $chunk_size;
$position += $chunk_size;
}
unset($info_array["close"]);
$info_array["cursor"]["offset"] = $position;
$info_array["commit"] = array();
$info_array["commit"]["path"] = '/'. $destination_folder . '/' . $file_name;
$info_array["commit"]["mode"] = array();
$info_array["commit"]["mode"][".tag"] = "overwrite";
$info_array["commit"]["autorename"] = true;
$info_array["commit"]["mute"] = false;
$info_array["commit"]["strict_conflict"] = false;
$headers[2] = 'Dropbox-API-Arg: '. json_encode($info_array);
curl_setopt($ch, CURLOPT_URL, $finish_url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_POSTFIELDS, $tosend > 0 ? fread($fp, $tosend) : null);
curl_exec($ch);
curl_close($ch);
fclose($fp);
unlink($single_folder_file); // Remove files from server folder
}
}