Dropbox - 从网址上传文件无法始终如一地工作



我有一个将文件上传到Dropbox的PHP脚本。当我从命令行将其作为独立脚本运行时,它运行良好。

但是,当我将代码合并到更大的项目中时,文件无法上传,cURL 返回"errno"0(意思是没有 cURL 错误),并且 Dropbox 的 API 没有输出。

以下是有效的代码:

    $token = '<token>';
$url = "https://content.dropboxapi.com/2/files/upload";
    $post_body = file_get_contents("/other/server/url/test.txt");
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url); 
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Authorization: Bearer ' . $token,
                                           'Content-Type: application/octet-stream', 
                                           'Dropbox-API-Arg: {"path": "/Dropbox/path/subfolder/test.txt","mode": "add", "autorename": true, "mute": false}'));
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_body); 

curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 
$data = json_decode(curl_exec($ch), true);
curl_close($ch); 
print_r($data);

....这是损坏的代码:

private function dropbox_uploadFile( $path, $file_source, $file_name = "test1.txt") {

    echo "<br /><br />PATH: ". $path . '/' . $file_name . "<br /><br />";
    echo "<br /><br />SOURCE: ". $file_source . "<br /><br />";

    $token = '<token>';
    $url = "https://content.dropboxapi.com/2/files/upload";
    $post_body = file_get_contents( $file_source );
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url); 
    curl_setopt($ch, CURLOPT_HTTPHEADER, array('Authorization: Bearer ' . $token,
                                               'Content-Type: application/octet-stream', 
                                               'Dropbox-API-Arg: {"path": ' . $path.'/'.$file_name. '","mode": "add", "autorename": true, "mute": false}'));
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $post_body); 
    curl_setopt($ch,CURLOPT_SSL_VERIFYPEER, false);  // to prevent cURL error #60
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 
    $data = json_decode(curl_exec($ch), true);
    if( ! $data ) {
        echo "<pre>";
        print_r(curl_getinfo($ch));
        echo "</pre>";
        echo "ERROR: " . curl_errno( $ch ) . "<br /><br />";
    }
    curl_close($ch); 
    print_r($data);

}

我分解了 API 调用本身,如下所示:

$res = curl_exec($ch);
print_r($res);
$data = json_decode($res, true);

这向我展示了来自 API 的实际错误:

调用 API 函数"files/upload"时出错:HTTP 标头"Dropbox-API-Arg":无法将输入解码为 JSON

对于不同类型的错误,API 将返回纯文本或 JSON,响应Content-Type标头会告诉您是哪个错误。在您的代码中,您只处理 JSON,当未提供有效的 JSON 时,json_decode显然会静默失败。

无论如何,该错误指示为上传参数提供的 JSON 本身无效。问题似乎是path值开头缺少引号,修复在这里:

curl_setopt($ch, CURLOPT_HTTPHEADER, array('Authorization: Bearer ' . $token,
                                           'Content-Type: application/octet-stream',
                                           'Dropbox-API-Arg: {"path": "' . $path.'/'.$file_name. '","mode": "add", "autorename": true, "mute": false}'));

我去这里尝试了一些技巧,我使用 SWIFT。希望可以帮助他人。在与保管箱支持进行一些(硬)邮件之后...

在我的情况下,错误是由于路径中无法转义的特殊字符。如果要上传:

let unescapedFileName = "αβγ.jpg"

你必须逃脱:

    let unescapedFileName = "αβγ.jpg"
    let escapedFileName  = DB_asciiEscape(unescapedFileName)

这里有一个单元测试:

   func testUtf8Decode(){
        
        let unescapedFileName = "αβγ.jpg"
        let escapedFileName  = DB_asciiEscape(unescapedFileName)
        print(escapedFileName)
        
        let contains = escapedFileName.contains("\u03b1\u03b2\u03b3")
        XCTAssert(contains, "not escaped")
        
    }

其中函数为:

func DB_asciiEscape(_ s: String) -> String {
    
    let out = s.unicodeScalars.reduce("", { (partialResult: String, char: UnicodeScalar) -> String  in
    
        if !char.isASCII {
            return partialResult + String(format:"\u%04x", char.value)
        } else {
            if (char == "u{7F}") {
                return partialResult + "\u007f"
            } else {
                return partialResult + "(char)"
            }
        }
    })
    return out
}

相关内容

  • 没有找到相关文章

最新更新