2015年4月28日

Webapp2 教學 (7) - 檔案上傳 ( Upload files in Webapp2 tutorial )

除了基本的表單、JSON 資料傳遞之外,Web Application 常需要檔案上傳的功能,因此本篇將介紹怎麼在 Webapp2 的環境中實現上傳檔案的功能,文章內容將以圖片上傳為範例。( 其他 Webapp2 相關教學可以參考本篇整理 )



檔案上傳流程:
請參考我自製的流程圖:



前置作業:
 Google 提供的 Blobstore 是針對上傳大型檔案的需求,因此我們需要將 Blobstore 相關的 module 載入,參考如下:
from google.appengine.ext import blobstore
from google.appengine.ext.webapp import blobstore_handlers


建立檔案上傳頁面:
首先建立要上傳檔案的頁面與對應的 Handler,內容如下:
<!-- 上傳檔案頁面:uploadfile.html -->
<!-- 以下部分為基本上傳檔案的表單寫法 -->
<form action="{{upload_url}}" method="POST" enctype="multipart/form-data">
    <input type="file" name="file"/>
    <input type="submit"/>
</form>

<!-- 以下部分為檔案上傳完後,導回此頁並顯示檔案相關資訊 -->
<p>File Name : {{ filename }}</p>
<p>File Blob Key : {{ filekey }}</p>
{% if filekey != None %}
    <!-- 利用 Blobstore key 取得檔案 -->
    <img width="160" height="90" src="/servefile/{{ filekey }}" />
{% endif %}
此頁對應的 Request Handler 內容如下:
class UploadFilePage(webapp2.RequestHandler):
    def get(self):
        # 建立一個 Blobstore 的上傳路徑
        upload_url = blobstore.create_upload_url('/upload')

        # 將 Blobstore 上傳路徑傳至頁面表單的 action 屬性
        values = {"upload_url": upload_url}

        # 上傳完成後會導回此頁,並將相關參數傳入,利用參數顯示檔案名稱、預覽檔案
        if len(self.request.query) > 0:
            values['filename'] = self.request.params['filename']
            values['filekey'] = self.request.params['filekey']

        # 輸出畫面
        path = os.path.join(os.path.dirname(__file__), 'uploadfile.html')
        self.response.out.write(template.render(path, values))


實作檔案上傳功能:
剛建立好檔案上傳的頁面後,當表單依照 action="/upload" 送出之後,我們還需要建立負責處理的 Request Handler,更正確應該是說我們需要使用 BlobstoreUploadHandler 來處理。內容參考如下:
class UploadHandler(blobstore_handlers.BlobstoreUploadHandler):
    def post(self):
        # 取得已上傳檔案的 BlobInfo 物件
        file = self.get_uploads()[0]
        
        # 將已上傳檔案的資訊紀錄一起導回 uploadfile.html,
        query = "filename=" + file.filename + "&filekey="+str(file.key())
        self.redirect("/uploadfile?" + query)


取得儲存於 Blobstore 中的檔案:
前面幾個步驟已經將檔案上傳的功能完成。但在 uploadfile.html 中,我們還要實現預覽圖片的功能,也就是我們要實作取得 Blobstore 檔案的功能,程式內容參考如下:
class ServeFileHandler(blobstore_handlers.BlobstoreDownloadHandler):
    def get(self, filekey):
        # 利用 Blob key 來取得檔案
        if not blobstore.get(filekey):
            self.error(404)
        else:
            self.send_blob(filekey)


設定 Router:
Router 設定內容,範例如下:
app = webapp2.WSGIApplication([
    ('/upload', UploadHandler),
    ('/uploadfile', UploadFilePage),
    ('/servefile/([^/]+)?', ServeFileHandler)
], debug=True)


設定 Blobstore 儲存位置:
在測試環境中,相關資料儲放的位置為 /tmp/appengine.yourapp.yourusername/ 底下。為了方便,我們可以在啟動測試伺服器時指定資料存放位置,指令如下:。
python2 dev_appserver.py --storage_path=your/path yourapp


Environment :
  ・ Arch Linux
  ・ Python 2.7

Reference :
  ・ Webapp2 official site
  ・ Blobstore Python API
  ・ BlobInfo Class


熱門文章