Google Document にファイルをアップロードするバッチを作ってみた
GitHub に上げたので最新ソースは GitHub からどうぞ
http://github.com/limitusus/google_docs_up/
Motivation
普段研究室のサーバにログインして作業することが多いので、メールもサーバ上で Emacs を立ち上げ、その上で Mew を使ってメールを読んでいます。
ときどき添付ファイルつきメールが来ることもあるんですが、 .doc なファイルとか、 .xls なファイルとか、挙げ句の果てには .docx とか .xlsx とかが添付されてきます。
普段は Ubuntu しか使ってないので、 Openoffice.org を使って .doc や .xls まではギリギリ読めるのですが、 .docx とか来るとどうしようもなく、 Google Docs にアップロードすることで開くという対処法が存在していました。
前述したとおりメールはサーバ上で読んでいるので、アップロードを Web 上で行うためには、
- メールを受信する
- 添付ファイルをサーバ上のどこかに保存する
- 添付ファイルをローカルマシンに持ってくる
- Web上でアップロード処理を行う
- 添付ファイルを見る
というプロセスが必要です。これはいかにも時間がかかる作業で、真のプログラマなら面倒で到底やってられないでしょう。
自然に考えて、
- メールを受信する
- 添付ファイルをサーバ上のどこかに保存する
- 添付ファイルをサーバから直接アップロードする
- 添付ファイルを見る
となっているべきです。
これを実現するため、 Google Documents の API を利用することにしました。
API の詳細はこちら。
Protocol Guide (v3.0) - Google Documents List Data API v3.0 - Google Code
Get API Library
Google Documents の API ライブラリは以下のページから入手できます。
Client Libraries and Sample Code - Google Documents List Data API - Google Code
今回は Python の SVN から引っ張ってくることに。
Python Client Library Project -> Source
とたどると、チェックアウトの方法が分かります。ここには Subversion によるチェックアウト方法が書かれています。
tarball でも SVN でも、とにかく持ってきて展開すれば、 setup.py などが手に入ります(ここでは git-svn でチェックアウトしました)。
~/git/gdata-python-client % ls INSTALL.txt MANIFEST README.txt RELEASE_NOTES.txt build pydocs samples setup.py src tests
Install API Library
API ライブラリをインストールします。これは setup.py がやってくれます。詳しくは INSTALL.txt を読んでください。
私はいつも ~/local 以下にいろいろ置くことにしているので
~/git/gdata-python-client % ./setup.py install --home=$HOME/local
としてインストールしました。
これにより、 $HOME/local/lib/python 以下に Google Documents API Library がセットアップされます。
このようにセットアップを行った場合、環境変数 PYTHONPATH に $HOME/local/lib/python が含まれている必要があります。必要に応じて設定します。
Modify API Library
実は 2009/09/29 現在の Python の API は PDFのアップロードに対応していません(Java は対応しているらしい)。
そこで、少し修正を行います。
Issue 591 - gdata-issues - Allow Upload of PDF Files to Google Docs - Project Hosting on Google Codeの Comment: 77 に修正が書かれています。
修正するファイルは [--home で指定したディレクトリ]/lib/python/gdata/docs/service.py です。
- uri = の行の変更
- GData-Version の追加
の2ヶ所です。
Usage
作成したプログラムに実行権限を付けて PATH を通しておけば、
$ google-docs-up hoge.pdf $ google-docs-up hoge.docx
などとするだけでファイルがアップロードされ、閲覧するための URI が表示されます。
% google_docs_up hoge.pdf ('hoge.pdf', 'hoge.pdf', 'pdf') Document now accessible online at: http://docs.google.com/fileview?id=ファイルID Current Documents list: hoge.pdf
のように出力され、上で表示された URI にアクセスすれば Google Documents 上でファイルを閲覧できます。
コードは続きで。
コードを書く
実際に書いてみたのがこれです。
ちょっと前の API の名残で面倒なことやってますが、修正も面倒なので放置しています。
(前の API では各ファイル種類毎に別々のアップロードメソッドを指定する必要がありましたが、現在は Upload に統一されています。多分今は拡張子による分岐は不要でしょう。)
#!/usr/bin/env python2.5 # -*- python -*- import gdata.docs.service import sys, os # Create a client class which will make HTTP requests with Google Docs server. client = gdata.docs.service.DocsService() # Authenticate using your Google Docs email address and password. client.ClientLogin('ユーザ名', 'パスワード') # Upload Specified File filepath = sys.argv[1] filename = filepath.split("/")[-1] # Determine FILETYPES suffix = filename.split(".")[-1].lower() ft = None uploadfunc = None is_upload = True """ { 'RTF': 'application/rtf', 'PPT': 'application/vnd.ms-powerpoint', 'ZIP': 'application/zip', 'DOC': 'application/msword', 'HTM': 'text/html', 'ODS': 'application/x-vnd.oasis.opendocument.spreadsheet', 'ODT': 'application/vnd.oasis.opendocument.text', 'TXT': 'text/plain', 'SWF': 'application/x-shockwave-flash', 'PPS': 'application/vnd.ms-powerpoint', 'HTML': 'text/html', 'TAB': 'text/tab-separated-values', 'SXW': 'application/vnd.sun.xml.writer', 'TSV': 'text/tab-separated-values', 'PDF': 'application/pdf', 'CSV': 'text/csv', 'XLS': 'application/vnd.ms-excel', 'PNG': 'image/png' } """ uploadfunc = client.Upload if suffix in ('doc', 'docx'): ft = 'DOC' elif suffix in ('xls', 'xlsx'): ft = 'XLS' elif suffix in ('ppt', 'pptx'): ft = 'PPT' elif suffix == 'pdf': ft = 'PDF' else: is_upload = False print "Unknown suffix. Don't upload" if is_upload: print (filepath, filename, suffix) ms = gdata.MediaSource(file_path=filepath , content_type=gdata.docs.service.SUPPORTED_FILETYPES[ft]) entry = uploadfunc(media_source=ms, title=filename) print 'Document now accessible online at:', entry.GetAlternateLink().href print "Current Documents list: \n" # Query the server for an Atom feed containing a list of your documents. documents_feed = client.GetDocumentListFeed() # Loop through the feed and extract each document entry. for document_entry in documents_feed.entry: # Display the title of the document on the command line. print document_entry.title.text