通过 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 机制。上传机制有几个部分需要按以下顺序使用:

  1. 呼叫/files/upload_session/start。在以下方法中使用生成的 session_id 作为参数,以便 Dropbox 知道您正在与哪个会话交互。
  2. 将文件的每个 "chunk" 递增地传递给 /files/upload_session/append_v2。需要注意的几件事:

    • 第一个调用将return一个cursor,用于以特定顺序遍历文件的块。它在每次连续调用此方法时作为参数传递(光标在每次响应时更新)。
    • final 调用必须包含 属性 "close": true,这会关闭会话以便上传。
  3. 将最终的 cursor(和 commit 信息)传递给 /files/upload_session/finish。如果您在响应中看到新的文件元数据,那么 您做到了!!

我知道这是一个旧的 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
    }
}