Lately I’ve been working on an app that uses the Google Docs GData API. I’ve found that Google Apps shares a lot of the properties that make SharePoint development particularly interesting:

  • Searching for error messages doesn’t help much because the platform and its bugs are quite new

  • The tools have pieces missing and don’t quite work as they should

  • Documentation is inadequate at best

One of the most obviously missing functions in the API is the ability to download a document. I found a workaround on google groups easily enough, creating the http request manually and setting the Authorization header, but unfortunately that doesn’t seem to work for hosted accounts.

With a few wrong turns trying to get a new auth token manually, it took me a full day of trial and error to find something that worked - setting a cookie and adding the hosted domain name to the start of the auth token.

To save anyone else from going through the same process, here’s the code:


        public static string DownloadDocumentFromAltUri(string altUri, string token)
            var service = GetService(token);
            string docurl;
            string domain = null;

            var docId = altUri.ToDocumentId();

            if (altUri.Contains(""))
                // google apps

                var s1 = altUri.Substring(altUri.IndexOf("") + 18);
                domain = s1.Substring(0, s1.IndexOf("/"));

                docurl = string.Format("{0}/RawDocContents?revision=_latest&docID={1}&justBody=true&browserok=true", domain, docId);
                // google docs
                docurl = string.Format("{0}&justBody=true&browserok=true", docId);

            Debug.WriteLine(string.Format("Downloading. DocId={0}, AltUri={1}, DocUri={2}", docId, altUri, docurl));

            HttpWebRequest wreq = (HttpWebRequest)HttpWebRequest.Create(docurl);
            if (UseAuthSub)
                wreq.Headers.Add("Authorization", string.Format("AuthSub token={0}", token));
                var authToken = ((GDataGAuthRequestFactory)service.RequestFactory).QueryAuthToken(service.Credentials);

                if (string.IsNullOrEmpty(domain))
                    // unhosted accounts should accept this header
                    wreq.Headers.Add("Authorization", string.Format("GoogleLogin auth={0}", authToken));




            wreq.KeepAlive = true;
            var wresp = wreq.GetResponse();
            var stream1 = wresp.GetResponseStream();
            var cl = wresp.ContentLength;
            StreamReader sr = new StreamReader(stream1);
            var resp = sr.ReadToEnd();
            return resp;