Downloading Documents with the Google Docs API
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("docs.google.com/a/"))
{
// google apps
var s1 = altUri.Substring(altUri.IndexOf("docs.google.com/a/") + 18);
domain = s1.Substring(0, s1.IndexOf("/"));
docurl = string.Format("http://docs.google.com/a/{0}/RawDocContents?revision=_latest&docID={1}&justBody=true&browserok=true", domain, docId);
}
else
{
// google docs
docurl = string.Format("http://docs.google.com/RawDocContents?revision=_latest&docID={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));
}
else
{
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));
}
else
{
wreq.Headers.Add("Cookie",
string.Format("WRITELYH={0}={1}",
domain,
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;
}