【问题】
参考百度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的错误