Python 谷歌应用引擎下载链接

Python 谷歌应用引擎下载链接,python,google-app-engine,download,Python,Google App Engine,Download,我在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 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,这样我就可以计算下载量并查看谁在热链接

我不想阻止热链接,只要网站使用此url,真实路径就会隐藏/不可用。通过这种方式,我可以计算下载量,即使它来自Google Analytics或Clicky显然无法处理的外部,而日志保留期只有大约90天,因此不方便

问题是:如何制作一个python处理程序来为用户启动文件下载?就像我们在很多php/asp网站上看到的那样

在搜索了大量内容并阅读了这两条线索之后,我似乎可以得到如下结果:

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的URL,但实际上是用python处理的,因此我可以检查引用者,计算下载量,等等

这些文件实际上位于不同的子文件夹中,由于路径的生成方式,它们不会被真正的直接下载。我不知道除了“/”和“\”之外是否还有其他字符需要过滤掉,但这样一来,任何人都不能访问父文件夹中的任何其他文件

虽然我真的不知道这一切对我的配额和文件大小限制意味着什么

app.yaml

main.py


您可以将文件内容存储在blob存储中并从那里提供服务,但如果文件太大且客户端速度较慢,您将达到30秒的时间限制

另一个选择是使用一个简单的处理程序来计算下载次数,然后发出临时重定向HTTP 302到真实下载链接。它允许您提供大文件,但仍然可以热链接真实文件而不是处理程序URL。

您可以尝试使用self.resquest.referer

这是你能做到的。点击此处下载链接到您的文件下载页面,然后您可以有一个FileDownloadHandler,其中名称/id/或whaterver作为参数传递,在该处理程序中,检查referer是否为“下载页面”,以便您知道请求是否为有效下载。如果是,则提供文件,如果不是,则重定向或执行一些错误


只是一个想法

只要你的文件很小,这就行了。如果它们较大,您应该将它们存储在blobstore中,并使用直接blobstore支持为它们提供服务,这样您就不必将它们读入应用程序中的内存。请求时间限制为60秒,而不是30秒,并且它们不适用于上载或下载时间-因此,无论大小,使用blobstore都可以正常工作。
handlers:
- url: /(.*\.rar)
  script: main.app
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)