【问题】
参考百度API的官网:
http://developer.baidu.com/wiki/index.php?title=docs/pcs/rest/file_data_apis_list
中的“上传单个文件”的解释:
上传单个文件API演示 功能 上传单个文件。 百度PCS服务目前支持最大2G的单个文件上传。 HTTP请求方式 POST URL https://pcs.baidu.com/rest/2.0/pcs/file 请求参数 参数名称 类型 是否必需 描述 method string 是 固定值,upload。 access_token string 是 开发者准入标识,HTTPS调用时必须使用。 path string 是 上传文件路径(含上传的文件名称)。 注意:
file char[] 是 上传文件的内容。 ondup string 否
注意:
返回参数 参数名称 类型 UrlEncode 描述 path string 是 该文件的绝对路径。 size uint64 否 文件字节大小。 ctime uint64 否 文件创建时间。 mtime uint64 否 文件修改时间。 md5 string 否 文件的md5签名。 fs_id uint64 否 文件在PCS的临时唯一标识ID。 示例 请求示例: POST https://pcs.baidu.com/rest/2.0/pcs/file?method=upload&path=%2fapps%2falbum%2f1.JPG&access_token=b778fb598c717c0ad7ea8c97c8f3a46f 响应示例: {
"path" : "/apps/album/1.jpg",
"size" : 372121,
"ctime" : 1234567890,
"mtime" : 1234567890,
"md5" : "cb123afcc12453543ef",
"fs_id" : 12345,
"request_id":4043312669
} |
并且也参考了:
http://developer.baidu.com/wiki/index.php?title=docs/pcs/rest/overview
中所解释的POST的例子:
2. POST请求:
方式一: POST /rest/2.0/pcs/quota?key2=value2&key3=value3 HTTP/1.1 User-Agent: curl/7.12.1 (x86_64-redhat-linux-gnu) libcurl/7.12.1 OpenSSL/0.9.7a zlib/1.2.1.2 libidn/0.5.6 Pragma: no-cache Accept: */* Host:pcs.baidu.com Content-Length:123 Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryS0JIa4uHF7yHd8xJ ------WebKitFormBoundaryS0JIa4uHF7yHd8xJ Content-Disposition: form-data; name="key1" value1 ------WebKitFormBoundaryS0JIa4uHF7yHd8xJ— 方式二: POST /rest/2.0/pcs/quota HTTP/1.1 User-Agent: curl/7.12.1 (x86_64-redhat-linux-gnu) libcurl/7.12.1 OpenSSL/0.9.7a zlib/1.2.1.2 libidn/0.5.6 Pragma: no-cache Accept: */* Host:pcs.baidu.com Content-Length:123 Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryS0JIa4uHF7yHd8xJ ------WebKitFormBoundaryS0JIa4uHF7yHd8xJ Content-Disposition: form-data; name="key1" value1 ------WebKitFormBoundaryS0JIa4uHF7yHd8xJ Content-Disposition: form-data; name="key2" value2 ------WebKitFormBoundaryS0JIa4uHF7yHd8xJ Content-Disposition: form-data; name="key3" value3 ------WebKitFormBoundaryS0JIa4uHF7yHd8xJ-- |
然后用代码:
string[] token = respTokenJson.Split(',');
string tokenStr = token[2].Split(':')[1].Trim('"');
byte[] fileBytes = null;
string filename = "fileForUpload2.txt";
string fullFilePath = @"d:\" + filename;
using (FileStream fs = new FileStream(fullFilePath, FileMode.Open))
{
fileBytes = new byte[fs.Length];
fs.Read(fileBytes, 0, fileBytes.Length);
}
StringBuilder buffer = new StringBuilder();
char[] fileCh = new char[fileBytes.Length];
for (int i = 0; i < fileBytes.Length; i++)
fileCh[i] = (char)fileBytes[i];
buffer.Append(fileCh);
//postDict = new Dictionary<string, string>();
//postDict.Add("file", buffer.ToString());
string postDataStr = buffer.ToString();
string uploadSingleFileUrl = "https://pcs.baidu.com/rest/2.0/pcs/file?";
Dictionary<string, string> queryParaDict = new Dictionary<string, string>();
queryParaDict.Add("method", "upload");
queryParaDict.Add("access_token", tokenStr);
queryParaDict.Add("path", "/apps/测试应用/" + filename);
uploadSingleFileUrl += crifanLib.quoteParas(queryParaDict);
curCookies = crifanLib.getCurCookies();
newCookies = new CookieCollection();
foreach (Cookie ck in curCookies)
{
if (ck.Name == "BAIDUID" || ck.Name == "BDUSS")
{
ck.Domain = "pcs.baidu.com";
}
newCookies.Add(ck);
}
crifanLib.setCurCookies(newCookies);
string boundaryValue = "----WebKitFormBoundaryS0JIa4uHF7yHd8xJ";
string boundaryExpression = "boundary=" + boundaryValue;
headerDict = new Dictionary<string, string>();
headerDict.Add("Pragma", "no-cache");
headerDict.Add("Content-Type", "multipart/form-data;" + " " + boundaryExpression);
postDataStr = boundaryValue + "\r\n"
+ "Content-Disposition: form-data; name=\"file\"" + "\r\n"
+ postDataStr + "\r\n"
+ boundaryValue;
//string str = crifanLib.getUrlRespHtml(
// string.Format(@"https://pcs.baidu.com/rest/2.0/pcs/file?method=upload&path=%2Fapps%2F%E6%B5%8B%E8%AF%95%E5%BA%94%E7%94%A8%2F78.jpg&access_token={0}", tokenStr),
// headerDict, postDict);
string respJson = crifanLib.getUrlRespHtml(uploadSingleFileUrl, headerDict, null, null, postDataStr: postDataStr);结果出错,出现403:
【解决过程】
1。很明显,403是就是禁止访问,一般都是权限错误。
但是此处确保对应的access_token等值是正常的,即没有权限方面的错误的。
2.百度官网:
http://developer.baidu.com/wiki/index.php?title=docs/cplat/stor/faq
也说了,403的话,是:
返回403是什么意思?这种情况一般是权限验证没有通过。可能有如下几种情况:
|
3.后来别处调试的结果,貌似也是如预期的:
4.然后调试发现,此时的request header是,正常的:
{Accept: */* User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.3; .NET4.0C; .NET4.0E Accept-Encoding: gzip, deflate,gzip Content-Type: multipart/form-data; boundary=—-WebKitFormBoundaryS0JIa4uHF7yHd8xJ Host: pcs.baidu.com Cookie: $Version=1; BAIDUID=6D174687C22FA05F53A9DB633FC499D8:FG=1; $Path=/; BDUSS=5JTlV4aEMyMTJnc2hxYkpud3JFTldlMC02cjdRUHJXcGEtRnpXVmJoaWVSN05SQVFBQUFBJCQAAAAAAAAAAAEAAAAZP0gCYWdhaW5pbnB1dDMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ66i1GeuotRNH Content-Length: 180 Expect: 100-continue Connection: Keep-Alive } |
以及对应的post data是:
"—-WebKitFormBoundaryS0JIa4uHF7yHd8xJ Content-Disposition: form-data; name="file" 6222021102008788781 home abc: 6228480670539546416 —-WebKitFormBoundaryS0JIa4uHF7yHd8xJ" |
也符合其规范的。
但是结果就是不对,始终是403错误。
5.再去试试,把所有的,当然的cookie,都改为此处的domain:
curCookies = crifanLib.getCurCookies();
newCookies = new CookieCollection();
foreach (Cookie ck in curCookies)
{
//if (ck.Name == "BAIDUID" || ck.Name == "BDUSS")
//{
ck.Domain = "pcs.baidu.com";
//}
newCookies.Add(ck);
}
crifanLib.setCurCookies(newCookies);试试效果。
结果还是错误依旧。
6.后来又试了试:
string[] token = respTokenJson.Split(',');
string tokenStr = token[2].Split(':')[1].Trim('"');
byte[] fileBytes = null;
string filename = "fileForUpload2.txt";
string fullFilePath = @"d:\" + filename;
using (FileStream fs = new FileStream(fullFilePath, FileMode.Open))
{
fileBytes = new byte[fs.Length];
fs.Read(fileBytes, 0, fileBytes.Length);
}
StringBuilder buffer = new StringBuilder();
char[] fileCh = new char[fileBytes.Length];
for (int i = 0; i < fileBytes.Length; i++)
fileCh[i] = (char)fileBytes[i];
buffer.Append(fileCh);
//postDict = new Dictionary<string, string>();
//postDict.Add("file", buffer.ToString());
string fileDataStr = buffer.ToString();
string uploadSingleFileUrl = "https://pcs.baidu.com/rest/2.0/pcs/file?";
Dictionary<string, string> queryParaDict = new Dictionary<string, string>();
queryParaDict.Add("method", "upload");
queryParaDict.Add("access_token", tokenStr);
//queryParaDict.Add("path", "/apps/测试应用/" + filename);
//queryParaDict.Add("path", "/apps/测试应用/");
uploadSingleFileUrl += crifanLib.quoteParas(queryParaDict);
curCookies = crifanLib.getCurCookies();
newCookies = new CookieCollection();
foreach (Cookie ck in curCookies)
{
//if (ck.Name == "BAIDUID" || ck.Name == "BDUSS")
//{
ck.Domain = "pcs.baidu.com";
//}
newCookies.Add(ck);
}
crifanLib.setCurCookies(newCookies);
string boundaryValue = "----WebKitFormBoundaryS0JIa4uHF7yHd8xJ";
string boundaryExpression = "boundary=" + boundaryValue;
headerDict = new Dictionary<string, string>();
headerDict.Add("Pragma", "no-cache");
headerDict.Add("Content-Type", "multipart/form-data;" + " " + boundaryExpression);
string postDataStr = "";
postDataStr += boundaryValue + "\r\n"
+ "Content-Disposition: form-data; name=\"Filename\"" + "\r\n"
+ filename + "\r\n";
postDataStr += boundaryValue + "\r\n"
+ "Content-Disposition: form-data; name=\"path\"" + "\r\n"
+ "/apps/测试应用/" + "\r\n";
postDataStr += boundaryValue + "\r\n"
+ "Content-Disposition: form-data; name=\"Filedata\"; filename=\"" + filename + "\" \r\n"
+ "Content-Type: application/octet-stream" + "\r\n"
+ fileDataStr + "\r\n"
+ boundaryValue;
//postDataStr += boundaryValue + "\r\n"
// + "Content-Disposition: form-data; name=\"file\"" + "\r\n"
// + fileDataStr + "\r\n"
// + boundaryValue;
//string str = crifanLib.getUrlRespHtml(
// string.Format(@"https://pcs.baidu.com/rest/2.0/pcs/file?method=upload&path=%2Fapps%2F%E6%B5%8B%E8%AF%95%E5%BA%94%E7%94%A8%2F78.jpg&access_token={0}", tokenStr),
// headerDict, postDict);
string respJson = crifanLib.getUrlRespHtml(uploadSingleFileUrl, headerDict, null, null, postDataStr: postDataStr);结果错误依旧。
6.后来,参考:
http://developer.baidu.com/wiki/index.php?title=docs/pcs/guide/usage_example
以为,找到了之前的错误,然后去访问自己的:
可以看到所需要的界面,可以获得百度网盘创建文件夹并修改的那个权限了。
然后可以访问到:
对应的网页显示的是“百度 OAuth2.0”的那个界面了。
然后可以获得对应的:
access_token=3.60b12647a72d958bf77e07a4d58b8d93.2592000.1370768746.1057380247-758730
然后就再去写对应的代码:
void emulateBaiduApi_crifanProcess()
{
string respHtml = "";
Dictionary<string, string> headerDict;
HttpWebResponse resp;
//1. access https
headerDict = new Dictionary<string, string>();
headerDict.Add("allowautoredirect", "false");
headerDict.Add("Accept", "application/x-ms-application, image/jpeg, application/xaml+xml, image/gif, image/pjpeg, application/x-ms-xbap, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*");
//https://openapi.baidu.com/oauth/2.0/authorize?response_type=token&client_id=Gnwa0TAyuWHccReOq7DRVNDe&redirect_uri=oob&scope=netdisk
string getNetdiskTokenUrl = "https://openapi.baidu.com/oauth/2.0/authorize?response_type=token&client_id="
+ txbBaiduApiKey.Text
+ "&redirect_uri=oob&scope=netdisk";
resp = crifanLib.getUrlResponse(getNetdiskTokenUrl, headerDict);
//http://openapi.baidu.com/oauth/2.0/authorize?response_type=token&client_id=Gnwa0TAyuWHccReOq7DRVNDe&redirect_uri=oob&scope=netdisk
string redirectedAuthUrl = resp.Headers["Location"];
//2.access http
//respHtml = crifanLib.getUrlRespHtml(redirectedAuthUrl);
//4. get token value
//https://passport.baidu.com/v2/api/?loginliteinfo&username=againinput3&isPhone=false&tpl=dev&immediatelySubmit=false&t=1367831133264
string loginItemInfoUrl = "https://passport.baidu.com/v2/api/?loginliteinfo&username="
+ txbBaiduUsername.Text
+ "&isPhone=false&tpl=dev&immediatelySubmit=false";
respHtml = crifanLib.getUrlRespHtml(loginItemInfoUrl);
//token:'9563cab84ccd1ad32c8deccc6ea5cc19'
string tokenValue = "";
if (crifanLib.extractSingleStr(@"token:'(\w+)'", respHtml, out tokenValue))
{
headerDict = new Dictionary<string, string>();
headerDict.Add("Referer", getNetdiskTokenUrl);
/*
username=againinput3
&password=limaolin
&verifycode=
&mem_pass=on
&charset=utf-8
&index=0
&safeflg=0
&staticpage=http%3A%2F%2Fopenapi.baidu.com%2Fstatic%2Fcommon%2Fpopup_login%2Fv2Jump.html
&loginType=1
&tpl=dev
&codestring=
&token=587092c1d3efb35255f9bed00ade4a0d
&callback=parent.bdPass.api.loginLite._submitCallBack
*/
Dictionary<string, string> postDict = new Dictionary<string, string>();
postDict.Add("username", txbBaiduUsername.Text);
postDict.Add("password", txbBaiduPassword.Text);
postDict.Add("verifycode", "");
postDict.Add("mem_pass", "on");
postDict.Add("charset", "utf-8");
postDict.Add("index", "0");
postDict.Add("safeflg", "0");
string staticpage = "http://www.baidu.com/cache/user/html/jump.html";
postDict.Add("staticpage", staticpage);
postDict.Add("loginType", "1");
postDict.Add("tpl", "dev");
postDict.Add("codestring", "");
postDict.Add("token", tokenValue);
postDict.Add("callback", "parent.bdPass.api.loginLite._submitCallBack");
string baiduMainLoginUrl = "https://passport.baidu.com/v2/api/?login";
string loginBaiduRespHtml = crifanLib.getUrlRespHtml(baiduMainLoginUrl, headerDict, postDict);
//6. access encodeURI
//var url = encodeURI('http://openapi.baidu.com/static/common/popup_login/v2Jump.html?hao123Param=Tk1XVkF5Zmpoak5DMXVhV0kwZG5wNGFWRTViemhxYkVkLWJVbEtOMm81UTNad1NIbE5SbGMwVm5OU04xSlNRVkZCUVVGQkpDUUFBQUFBQUFBQUFBRUFBQUFaUDBnQ1lXZGhhVzVwYm5CMWRETUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFHeTZqRkZzdW94UldX&callback=parent.bdPass.api.loginLite._submitCallBack&index=0&codestring=&username=againinput3&phonenumber=&mail=&tpl=dev&u=https%3A%2F%2Fpassport.baidu.com%2F&needToModifyPassword=0&gotourl=&auth=fc27e128a189b7ff766828578bf9f39f017e0a68dc100cbd5c062500663ce589611355d10db1&error=0');
string encodeUri = "";
if (crifanLib.extractSingleStr(@"encodeURI\('(http.+?)'\);", loginBaiduRespHtml, out encodeUri))
{
//http://openapi.baidu.com/static/common/popup_login/v2Jump.html?hao123Param=Tk1XVkF5Zmpoak5DMXVhV0kwZG5wNGFWRTViemhxYkVkLWJVbEtOMm81UTNad1NIbE5SbGMwVm5OU04xSlNRVkZCUVVGQkpDUUFBQUFBQUFBQUFBRUFBQUFaUDBnQ1lXZGhhVzVwYm5CMWRETUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFHeTZqRkZzdW94UldX&callback=parent.bdPass.api.loginLite._submitCallBack&index=0&codestring=&username=againinput3&phonenumber=&mail=&tpl=dev&u=https%253A%252F%252Fpassport.baidu.com%252F&needToModifyPassword=0&gotourl=&auth=fc27e128a189b7ff766828578bf9f39f017e0a68dc100cbd5c062500663ce589611355d10db1&error=0
respHtml = crifanLib.getUrlRespHtml(encodeUri);
}
//!!! prepare cookies
//BAIDUID C912FC868D7C8BF115F01C9B67AE55DE:FG=1
//BDUSS WRaNUptRUNORjE4aU5xNlpBaTVtYk1-ZWhCR0JpNzV0Z2s2YX5vUzVoeGd-NjVSQVFBQUFBJCQAAAAAAAAAAAEAAAAZP0gCYWdhaW5pbnB1dDMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGByh1FgcodRS
CookieCollection curCookies = crifanLib.getCurCookies();
CookieCollection newCookies = new CookieCollection();
foreach (Cookie ck in curCookies)
{
if (ck.Name == "BAIDUID" || ck.Name == "BDUSS")
{
ck.Domain = "openapi.baidu.com";
}
newCookies.Add(ck);
}
crifanLib.setCurCookies(newCookies);
headerDict = new Dictionary<string, string>();
headerDict.Add("allowautoredirect", "false");
resp = crifanLib.getUrlResponse(redirectedAuthUrl, headerDict);
//http://openapi.baidu.com/oauth/2.0/login_success#expires_in=2592000&access_token=3.8826e8f1743164248f505698ccfdeb59.2592000.1370769262.1057380247-758730&session_secret=b52efa6bb90ba462e0a08a119ae7226d&session_key=94rrl19KodEPm330pCKGu%2FD3HU%2FDFI4Hp8RnS7KdHaQOrJjFBReW%2FsAtwxCS7uarcpHM2ThiBhysJDABwpy1g3q%2FVJnUiec%3D&scope=basic+netdisk
string includeTokenUrl = resp.Headers["Location"];
txbRespTokenJson.Text = includeTokenUrl;
//http://openapi.baidu.com/oauth/2.0/login_success#expires_in=2592000&access_token=3.d316783ec1e6a9d86212dd22343914f0.2592000.1370771017.1057380247-758730&session_secret=3e46ebad3478e48db90901f01177ff3c&session_key=94q3jz3ociQ590uWfkgBkhVr5FbdUHdYMEEnI4T2rYkkUDcaBqzDm%2FveX5Vk4PJ1tSv6c4NQWq%2FbElZs%2Bxqd7Tg%2Fthh2eJI%3D&scope=basic+netdisk
string netdiskAccesstoken = "";
if (crifanLib.extractSingleStr(@"&access_token=(.+?)&", includeTokenUrl, out netdiskAccesstoken))
{
byte[] fileBytes = null;
string filename = "fileForUpload3.txt";
string fullFilePath = @"d:\" + filename;
using (FileStream fs = new FileStream(fullFilePath, FileMode.Open))
{
fileBytes = new byte[fs.Length];
fs.Read(fileBytes, 0, fileBytes.Length);
}
StringBuilder buffer = new StringBuilder();
char[] fileCh = new char[fileBytes.Length];
for (int i = 0; i < fileBytes.Length; i++)
fileCh[i] = (char)fileBytes[i];
buffer.Append(fileCh);
//postDict = new Dictionary<string, string>();
//postDict.Add("file", buffer.ToString());
string fileDataStr = buffer.ToString();
string uploadSingleFileUrl = "https://pcs.baidu.com/rest/2.0/pcs/file?";
Dictionary<string, string> queryParaDict = new Dictionary<string, string>();
queryParaDict.Add("method", "upload");
queryParaDict.Add("access_token", netdiskAccesstoken);
queryParaDict.Add("path", "/apps/测试应用/" + filename);
uploadSingleFileUrl += crifanLib.quoteParas(queryParaDict);
curCookies = crifanLib.getCurCookies();
newCookies = new CookieCollection();
foreach (Cookie ck in curCookies)
{
if (ck.Name == "BAIDUID" || ck.Name == "BDUSS")
{
ck.Domain = "pcs.baidu.com";
}
newCookies.Add(ck);
}
crifanLib.setCurCookies(newCookies);
string boundaryValue = "----WebKitFormBoundaryS0JIa4uHF7yHd8xJ";
string boundaryExpression = "boundary=" + boundaryValue;
headerDict = new Dictionary<string, string>();
headerDict.Add("Pragma", "no-cache");
headerDict.Add("Content-Type", "multipart/form-data;" + " " + boundaryExpression);
string postDataStr = "";
//postDataStr += boundaryValue + "\r\n"
// + "Content-Disposition: form-data; name=\"Filename\"" + "\r\n"
// + filename + "\r\n";
//postDataStr += boundaryValue + "\r\n"
// + "Content-Disposition: form-data; name=\"path\"" + "\r\n"
// + "/apps/测试应用/" + "\r\n";
//postDataStr += boundaryValue + "\r\n"
// + "Content-Disposition: form-data; name=\"Filedata\"; filename=\"" + filename + "\" \r\n"
// + "Content-Type: application/octet-stream" + "\r\n"
// + fileDataStr + "\r\n"
// + boundaryValue;
postDataStr += boundaryValue + "\r\n"
+ "Content-Disposition: form-data; name=\"file\"" + "\r\n"
+ fileDataStr + "\r\n"
+ boundaryValue;
string respJson = crifanLib.getUrlRespHtml(uploadSingleFileUrl, headerDict, null, null, postDataStr: postDataStr);
}
}
}结果是,还是同样的403的错误,彻底无语了。
转载请注明:在路上 » 【未解决】通过百度API上传单个文件出现403的错误