[英]Download link with Google App Engine
我在Google App Engine上有一个静态网站,可以下载一些.rar文件。 现在,它由静态文件处理程序定义(app.yaml)处理:
handlers:
- url: /(.*\.(bz2|gz|rar|tar|tgz|zip))
static_files: static/\1
upload: static/(.*\.(bz2|gz|rar|tar|tgz|zip))
现在,我想要提供的是/download?MyFile.rar这样的下载链接,这样我就可以计算下载次数并查看谁在进行热链接 。
只要网站使用此网址,我就不想阻止热链接(真实路径将被隐藏/不可用)。 这样,即使下载来自外部(Google Analytics(分析)或Clicky显然不能处理,并且日志保留仅90天左右,也不方便),我也可以对其进行计数。
问题是:如何制作一个可以为用户启动文件下载的python处理程序? 就像我们在许多php / asp网站上看到的那样。
经过大量搜索并阅读了这2个线程( 我如何让Google App Engine具有从数据库中下载内容的下载链接? , google App Engine下载包含文件的文件 ),看来我可能有类似以下内容:
self.response.headers['Content-Type'] = 'application/octet-stream'
self.response.out.write(filecontent) # how do I get that content?
#or
self.response.headers["Content-Type"] = "application/zip"
self.response.headers['Content-Disposition'] = "attachment; filename=MyFile.rar" # does that work? how do I get the actual path?
我确实读过一个处理程序只能在有限的时间内运行,因此对于大文件可能不起作用?
任何指导将不胜感激!
谢谢。
罗姆兹
编辑:正常工作,它使我可以为所有.rar文件提供一个处理程序。 它可以让我拥有看起来像直接链接的网址(example.com/File.rar),但实际上是在python中处理的(因此我可以检查引荐来源网址,计算下载量等)。
文件实际上位于不同的子文件夹中,并且由于生成路径的方式而受到保护,免受真正的直接下载 。 我不知道是否还有其他字符(“ /”和“ \\”除外)应该被过滤掉,但是这种方式没有人可以访问父文件夹中的任何其他文件或其他任何内容。
虽然我真的不知道这对我的配额和文件大小限制意味着什么。
app.yaml
handlers:
- url: /(.*\.rar)
script: main.app
main.py
from google.appengine.ext import webapp
from google.appengine.api import memcache
from google.appengine.ext import db
import os, urlparse
class GeneralCounterShard(db.Model):
name = db.StringProperty(required=True)
count = db.IntegerProperty(required=True, default=0)
def CounterIncrement(name):
def txn():
counter = GeneralCounterShard.get_by_key_name(name)
if counter is None:
counter = GeneralCounterShard(key_name=name, name=name)
counter.count += 1
counter.put()
db.run_in_transaction(txn)
memcache.incr(name) # does nothing if the key does not exist
class MainPage(webapp.RequestHandler):
def get(self):
referer = self.request.headers.get("Referer")
if (referer and not referer.startswith("http://www.example.com/")):
self.redirect('http://www.example.com')
return
path = urlparse.urlparse(self.request.url).path.replace('/', '').replace('\\', '')
fullpath = os.path.join(os.path.dirname(__file__), 'files/'+path)
if os.path.exists(fullpath):
CounterIncrement(path)
self.response.headers['Content-Type'] = 'application/zip'
self.response.headers["Content-Disposition"] = 'attachment; filename=' + path
self.response.out.write(file(fullpath, 'rb').read())
else:
self.response.out.write('<br>The file does not exist<br>')
app = webapp.WSGIApplication([('/.*', MainPage)], debug=False)
您可以将文件内容存储在Blob存储中并从那里进行服务,但是如果文件过大且客户端运行缓慢,则会达到时间限制(约30秒)
另一个选择是拥有一个简单的处理程序,该处理程序对下载进行计数,然后发出临时重定向(HTTP 302)到实际的下载链接。 它可以让您处理大型文件,但仍然可以热链接实际文件而不是处理程序URL。
您可以尝试使用self.resquest.referer
。
这是您的方法。 单击“单击此处”以下载到文件下载页面的链接,然后可以使用FileDownloadHandler
,其中将name
/ id
/或whaterver作为参数传递,在此处理程序中,检查引荐来源网址是否为“下载页面”因此您知道请求是否为有效下载。 如果是的话,请提供文件;否则,请重定向或执行某些错误。
只是一个主意
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.