这些天有个项目是需要一部分Android开发。本想去官网看文档,众所周知的原因,官网无法连接。下载了本地的文件,由于是做的整站镜像,搜索功能无法正常使用,这对于经常要使用此功能的我来说很是麻烦。于是想到了把文件上传到GAE,再利用Google的本地功能来实现。 想的很简单,写好了app.yaml就要上传。谁知道试了几次也不成功。帮助手册上说的很明确:
| 限制 | 值 |
|---|---|
| 请求大小 | 10 兆字节 |
| 响应大小 | 10 兆字节 |
| 请求持续时间 | 30 秒 |
| 同时动态请求 | 30 * |
| 应用程序文件的最大数目 | 1,000 |
| 静态文件的最大数目 | 1,000 |
| 应用程序文件的最大大小 | 10 兆字节 |
| 静态文件的最大大小 | 10 兆字节 |
| 所有应用程序和静态文件的最大总大小 | 150 兆字节 |
看了看要上传的文件夹,5000多个文件,小气的google根本满足不了我。 想到Python的灵活性,在手册中翻了到了zipfile类库。有门!就上传zip文档,边解压边浏览。Google要用时间来换空间那就累死他的CPU 写个GAE应用loadzip.py:
#!/bin/env python
##
## This is a project for Google App Engine
## that support create a webisite by ZIP packages!
##
## By Litrin J. 2010/11
## Website: www.litrin.net
## Example: android-sdk.appspot.com
##
import wsgiref.handlers
from google.appengine.ext import webapp
from google.appengine.api import memcache
from zipfile import ZipFile
import os
import logging
import mimetypes
import re
class MainHandler(webapp.RequestHandler):
'''''
This is a project for Google App Engine that support create a webisite by ZIP packages!
'''
URL = ''
CACHEDTIME = 60*60*24*30
#setting memcaching time (seconds)
def get(self):
self.URL=self.request.path
if ( self.URL[-1:] == '/'):
#Get the defaule file for the path
self.URL+='index.html'
sRealFileName = os.getcwd() + self.URL
if (os.path.exists(sRealFileName)):
#If the file not be ziped, read it drictory
fNoZipedFile = open(sRealFileName,'r')
Entry = fNoZipedFile.read()
fNoZipedFile.close()
else:
Entry = self.loadFile()
self.buildMineType()
#Set the Mine type in header
if (self.response.headers['Content-Type'] == 'text/html'):
Entry = self.regex(Entry)
self.response.out.write(Entry)
#Response building finished!
def loadZipFile(self):
#Load the file from zip files. This is the core function!
lFilename = self.URL.split('/')
iPathLevel = 1
#Loop count, The dir layers
bLoaded = False
#Sucessful marks
while(iPathLevel < = len(lFilename)):
#Get the zip file name and the filename from the URL, support muli-layer
sFilePath = os.getcwd()
sFileName = ''
iElementCount = 1
for sElement in lFilename:
#Set or reset the Zip filename
if ( iElementCount <= iPathLevel):
sFilePath += sElement + '/'
if ( iElementCount >= iPathLevel ):
sFileName += sElement + '/'
iElementCount += 1
sFileName = sFileName[0:-1]
sZipFilename = sFilePath[0:-1] + '.zip'
if (os.path.exists(sZipFilename)):
#Found the Zip file
ZipFileHandle = ZipFile(sZipFilename)
Entry = ZipFileHandle.read(sFileName)
bLoaded = True
ZipFileHandle.close()
if (Entry is not None):
logging.info(sFileName + " in " + sZipFilename + " Loaded!")
return Entry
break
iPathLevel +=1
if (bLoaded==False):
#Can't file the file in Zip packages
logging.error('No found ' + self.request.path + '' +sZipFilename+' !')
self.error(404)
return None
def loadFile(self):
#Load in from memcache if cached
Entry = self.loadFromMemcach()
if Entry is None:
#If not cached, cache it
Entry = self.loadZipFile()
if(Entry is not None):
self.writeToMemcache(Entry)
return Entry
def loadFromMemcach(self):
memcachkey = self.URL
#The cache key is URL
Entry = memcache.get(memcachkey)
if Entry is not None:
return Entry
else:
return None
def writeToMemcache(self, data):
memcachkey = self.URL
#set the URL as the key
memcache.add(memcachkey, data, self.CACHEDTIME)
logging.info(memcachkey + ' cached!')
return True
def buildMineType(self):
#Building the MineType in Http header
sFilename = os.path.basename(self.URL)
lFileName = sFilename.split(".")
sExFilename = lFileName.pop()
#Get the file ex-filename
mimetypes.init()
sMineType = mimetypes.types_map['.'+sExFilename]
if (sMineType == ''):
#Others can't be idented, set to HTML
sMineType = 'text/html'
self.response.headers['Content-Type'] = sMineType
#Send Content-type
def regex(self, Entry):
lRegGroup=(
('n+', 'n'),
#
('t+', 't'),
#
)
for sRegCell in lRegGroup:
(sSource, sTarget) = sRegCell
rInfo = re.compile(sSource)
Entry = rInfo.sub(sTarget, Entry)
return Entry
def main():
application = webapp.WSGIApplication([('.*', MainHandler)], debug=True)
wsgiref.handlers.CGIHandler().run(application)
if __name__ == '__main__':
main()
比较简单,我也没有写太多注释。考虑到Google一直被这么搞,挂掉也不好,于是启用了memcache。 重写app.yaml
application: android-sdk version: 1 runtime: python api_version: 1 handlers: - url: .* script: zipload.py #- url: / # static_files: index.html # upload: index.html
准备就绪,把手册中每一个子目录压缩成zip,极限大小也无所谓,然后把手册根目录下的所有文件和这两个文件放在同一目录下。上传至GAE便可。 捎带说下,由于GAE还有对文件大小的限制。用此方法还无法完全解决Adroid手册上传的问题,后来我用了分级的目录结构搞定的,原理上跟上面是一致的,在此不再累述了。 把我的Android手册网站共享给大家 http://android-sdk.appspot.com/index.html PS:
- Linux下的Idle工具真烂,远不及以及够烂的windows版。好在SPE这个工具很好用。
- GAE的sdk for linux没有桌面工具,只能用命令行方式,在此代表Linux用户表示抗议!
本项目的后续版本已经通过google code开源,敬请访问:
http://code.google.com/p/zipsite/
获取最新版本
转载请注明:爱开源 » 突破GAE文件数量的限制