Google Doc API研究之一:模拟页面上传任意类型文件
一直以來想要做個程序,將google doc用作網盤,程序做 的差不多了才發現不是所有的人都可以上傳任意類型的文件,只有商業用戶才可以。商業用戶是要交錢的的,這與我們倡導的免費精神相關太遠。怎么辦,我的心血 不能白費,google還算厚道沒有把門關死,可以通過form的形式上傳,我們可以模擬form的動作,就能上傳了。好了費話少話,說實在的。
Google在上傳時要進行身份驗證。取得身份驗證后,提出上傳要求,這時返回一個上傳地址,然后上傳文件。下面一步步來。
第一步,通過網頁訪問DOC,其身份認證是通過cookie進行的,取得cookie的過程是
1、先訪問http://docs.google.com,它通過自動跳轉將你帶到一個登錄頁面。按登錄頁面中的頭部的set- cookie設置httpwebrequest的cookie,cookie中最重要的是HSID,然后設置url為 https://www.google.com/accounts/ServiceLoginAuth?service=writely 。然后設置提交數據ltmpl=homepage&continue=http://docs.google.com/& followup=http://docs.google.com/&service=writely&nui=1& rm=false&dsh={0}<mpl=homepage<mpl=homepage&GALX={1}& amp;Email={2}&Passwd={3}&rmShown=1&signIn=登錄&asts=
其中Email填google帳戶名,passwd填密碼,GALX可以從cookie中找到,dsh可從頁面的數據中得到。
2、再訪問網址:https://www.google.com/accounts /CheckCookie?continue=http%3A%2F%2Fdocs.google.com%2F&followup=http %3A%2F%2Fdocs.google.com%2F&service=writely<mpl=homepage& chtml=LoginDoneHtml,取得下一步的訪問地址,
3、再訪問網 址:http://docs.google.com/?auth=.......,根據回應設置cookie,這時的cookie就是可以訪問相當于 doc api中的token了。cookie中包含三條記錄HSI,SID,writelySID。
下面是原程序:
private CookieContainer? GetAuthenticationCookie(string User,string Passwd)
??????? {
??????????? string GALX;
??????????? string dsh;
??????????? string resText = "";
??????????? CookieContainer Auth = new CookieContainer();
??????????? //第一步
??????????? HttpWebRequest req = CreatRequest("http://docs.google.com/");
??????????? req.Method = "POST";
??????????? req.ContentLength = 0;
??????????? HttpWebResponse res = (HttpWebResponse)req.GetResponse();
??????????? //第二步
??????????? resText = getResponseText(res);
??????????? GALX = resText.Substring(resText.IndexOf("GALX") + 26, 11);
??????????? if ((resText.Substring(resText.IndexOf("dsh") + 32, 1)) == "-")
??????????????? dsh = resText.Substring(resText.IndexOf("dsh") + 32, 20);
??????????? else
??????????????? dsh = resText.Substring(resText.IndexOf("dsh") + 32, 19);
??????????? string postData = string.Format(
??????????????? "ltmpl=homepage&continue=http://docs.google.com/&followup=http: //docs.google.com/&service=writely&nui=1&rm=false&dsh= {0}<mpl=homepage<mpl=homepage&GALX={1}&Email={2}& amp; amp;Passwd={3}&rmShown=1&signIn=登錄&asts="
??????????????? , dsh, GALX, User, Passwd);
??????????? req = CreatRequest("https://www.google.com/accounts/ServiceLoginAuth?service=writely ");
??????????? req.AllowAutoRedirect = false;
??????????? req.Method = "POST";
??????????? //設置cookie及提交數據
??????????? Auth.Add(setCookie(res, "www.google.com"));
??????????? req.CookieContainer = Auth;
??????????? setPostData(req, postData);
??????????? res = (HttpWebResponse)req.GetResponse();
??????????? //第三步
??????????? req = CreatRequest(res.Headers["Location"]);
??????????? Auth.Add(setCookie(res, "www.google.com"));
??????????? req.CookieContainer = Auth;
??????????? res = (HttpWebResponse)req.GetResponse();
??????????? //第四步
??????????? resText = getResponseText(res);
??????????? string url = resText.Substring(resText.IndexOf("url=")).Split('\"')[0];
??????????? url = HttpUtility.HtmlDecode(url);
??????????? url = url.Substring(5, url.Length - 6);
??????????? req = CreatRequest(url);
??????????? req.Method = "GET";
??????????? req.AllowAutoRedirect = false;
??????????? Auth.Add(setCookie(res, "www.google.com"));
??????????? req.CookieContainer = Auth;
??????????? res = (HttpWebResponse)req.GetResponse();
??????????? Auth.Add(setCookie(res, "www.google.com"));
??????????? return Auth;
??????? }
??????? {
??????????? if (res.StatusCode != HttpStatusCode.OK)
??????????????? return null;
??????????? Stream dataStream = res.GetResponseStream();
??????????? StreamReader reader = new StreamReader(dataStream);
??????????? string str = reader.ReadToEnd();
??????????? reader.Close();
??????????? return str;
??????? }
??????? /// <summary>
??????? ///設置傳送的數據
??????? /// </summary>
??????? /// <param name="req">The req.</param>
??????? /// <param name="postData">The post data.</param>
??????? private void setPostData(HttpWebRequest req, string postData)
??????? {
??????????? byte[] bytes = Encoding.UTF8.GetBytes(postData);
??????????? req.ContentLength = bytes.Length;
??????????? using (Stream dataStream = req.GetRequestStream())
??????????? {
??????????????? dataStream.Write(bytes, 0, bytes.Length);
??????????????? dataStream.Close();
??????????? }
??????? }
??????? /// <summary>
??????? /// 根據response中頭部的set-cookie對request中的cookie進行設置
??????? /// </summary>
??????? /// <param name="setCookie">The set cookie.</param>
??????? /// <param name="defaultDomain">The default domain.</param>
??????? /// <returns></returns>
??????? private CookieCollection setCookie(HttpWebResponse res, string defaultDomain)
??????? {
??????????? string[] setCookie = res.Headers.GetValues("Set-Cookie");
??????????? // there is bug in it,the datetime in "set-cookie" will be sepreated in two pieces.
??????????? List<string> a = new List<string>(setCookie);
??????????? for (int i = setCookie.Length - 1; i > 0; i--)
??????????? {
??????????????? if (a[i].Substring(a[i].Length - 3) == "GMT")
??????????????? {
??????????????????? a[i - 1] = a[i - 1] + ", " + a[i];
??????????????????? a.RemoveAt(i);
??????????????????? i--;
??????????????? }
??????????? }
??????????? setCookie = a.ToArray<string>();
??????????? CookieCollection cookies = new CookieCollection();
??????????? foreach (string str in setCookie)
??????????? {
??????????????? NameValueCollection hs = new NameValueCollection();
??????????????? foreach (string i in str.Split(';'))
??????????????? {
??????????????????? int index = i.IndexOf("=");
??????????????????? if (index > 0)
??????????????????????? hs.Add(i.Substring(0, index), i.Substring(index + 1));
??????????????????? else
??????????????????????? switch (i)
??????????????????????? {
??????????????????????????? case "HttpOnly":
??????????????????????????????? hs.Add("HttpOnly", "True");
??????????????????????????????? break;
??????????????????????????? case "Secure":
??????????????????????????????? hs.Add("Secure", "True");
??????????????????????????????? break;
??????????????????????? }
??????????????? }
??????????????? Cookie ck = new Cookie();
??????????????? foreach (string Key in hs.AllKeys)
??????????????? {
??????????????????? switch (Key)
??????????????????? {
??????????????????????? case "Path":
??????????????????????????? ck.Path = hs[Key];
??????????????????????????? break;
??????????????????????? case "Expires":
??????????????????????????? ck.Expires = DateTime.Parse(hs[Key]);
??????????????????????????? break;
??????????????????????? case "Domain":
??????????????????????????? ck.Domain = hs[Key];
??????????????????????????? break;
??????????????????????? case "HttpOnly":
??????????????????????????? ck.HttpOnly = true;
??????????????????????????? break;
??????????????????????? case "Secure":
??????????????????????????? ck.Secure = true;
??????????????????????????? break;
??????????????????????? default:
??????????????????????????? ck.Name = Key;
??????????????????????????? ck.Value = hs[Key];
??????????????????????????? break;
??????????????????? }
??????????????? }
??????????????? if (ck.Domain == "") ck.Domain = defaultDomain;
??????????????? if (ck.Name != "") cookies.Add(ck);
??????????? }
??????????? return cookies;
??????? }
??????? /// <summary>
??????? /// 對request進行基本的設置
??????? /// </summary>
??????? /// <param name="URL">The URL.</param>
??????? /// <returns></returns>
??????? private HttpWebRequest CreatRequest(string URL)
??????? {
??????????? HttpWebRequest req = (HttpWebRequest)WebRequest.Create(URL);
??????????? req.UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.2.2) Gecko/20100316 Firefox/3.6.2";
??????????? req.ServicePoint.Expect100Continue = false;
??????????? req.ContentType = "application/x-www-form-urlencoded";
??????????? return req;
??????? }
整個過程很簡單,但調試花了我很長時間,主要是在https下調試走了很多彎路,一 開始使用httpanalyzer,結果有bug顯示的傳送數據總是重復。后來還是使用fiddler才解決。但使用fiddler時在https下會出 現證書與網站 不符的錯誤。
解決辦法是:
??????????? ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(ValidateServerCertificate);
??????? public static bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
??????? {
??????????? return true;
??????? }
第 一個函數在設置httpwebquest時調用就不會出現錯誤了。這時就可以用fiddler捕獲https包了。今天就寫到這里。
這里有幾點猜 想未證實,授權cookie中的writelySID及SID可能與google 的client的LSID和SID相同,但HSID不知從何而來。
cookie 可以反復使用,不用每次對話都要取得cookie。
代碼寫得很笨拙,大家不吝賜教。
下一步,研究上傳任意文件至指定目錄。
轉載于:https://www.cnblogs.com/zcmky/archive/2010/04/02/1703397.html
總結
以上是生活随笔為你收集整理的Google Doc API研究之一:模拟页面上传任意类型文件的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《财富》世界500强榜单公布 比亚迪首次
- 下一篇: 小型公司如何管理