我有一个将文件上传到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
}