curl Dropbox -从URL上传文件的功能不稳定

sqyvllje  于 2022-12-13  发布在  其他
关注(0)|答案(2)|浏览(148)

我有一个PHP脚本,可以上传文件到Dropbox。当我从命令行运行它作为一个独立的脚本,它的工作完美。
然而,当我将代码合并到更大的项目中时,文件无法上传,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);

}
eh57zj3b

eh57zj3b1#

I broke out the API call itself, like this:

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

That showed me the actual error from the API:
Error in call to API function "files/upload": HTTP header "Dropbox-API-Arg": could not decode input as JSON
For different types of errors, the API will return either plain text or JSON, with the response Content-Type header telling you which. In your code, you were only handling JSON, and json_decode apparently silently fails when it isn't supplied valid JSON.
Anyway, that error indicates the supplied JSON for the upload arguments is itself invalid. The problem seems to be a missing quote at the beginning of the path value, fixed here:

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}'));
pxq42qpu

pxq42qpu2#

我来这里尝试一些技巧,我正在使用SWIFT。希望能帮助其他人。经过一些(硬)邮寄与dropbox支持...
在我的情况下,错误是由于未转义的特殊字符在路径.如果你想上传:

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
}

相关问题