예제 #1
0
def file_download(filename):
    def send_chunk():  # 流式读取
        store_path = './upload/%s' % filename
        with open(store_path, 'rb') as target_file:
            while True:
                chunk = target_file.read(20 * 1024 * 1024)  # 每次读取20M
                if not chunk:
                    break
                yield chunk
    response = Response(send_chunk(), content_type='application/octet-stream')
    response.content_length = os.path.getsize('./upload/%s' % filename)
    return response
예제 #2
0
파일: proxy.py 프로젝트: bwhmather/LoPyPI
def get_file(package, filename):
    """
    """
    pypi = current_app.config['pypi']
    store = current_app.config['cached_file_store']

    content_type, _ = mimetypes.guess_type(filename)
    if content_type is None and filename.endswith(".egg"):
        content_type = "application/zip"

    f = store.get_file(package, filename)
    if f:
        # file is already cached locally.  Send it
        return send_file(f, mimetype=content_type)

    ## request file from pypi and stream it to client and disk
    # get url of remote file
    files = pypi.list_files(package)
    file_info = filter(lambda f: f['filename'] == filename, files)
    if not len(file_info):
        abort(404)
    file_info = file_info[0]
    uri = file_info['remote_uri']

    # start download
    download = requests.get(uri, stream=True)
    if download.status_code != 200:
        # TODO
        download.close()
        abort(download.status_code)

    def generate():
        # TODO this is f*****g ugly
        data_iter = download.iter_content(1024)
        outfile = tempfile.NamedTemporaryFile(delete=False)
        try:
            for data in data_iter:
                outfile.write(data)
                yield data
        finally:
            for data in data_iter:
                outfile.write(data)
            outfile.seek(0)

            # TODO verify checksum
            store.add_file(package, filename, outfile)

    response = Response(generate(), mimetype=content_type)
    if 'content-length' in download.headers:
        response.content_length = download.headers['content-length']

    return response
예제 #3
0
 def make_response(self):
     """读取远程的视频流,并伪装成本地的响应返回"""
     header, data_iter = self.get_stream()
     if self.type == "hls":
         resp = Response(data_iter, status=200)
     elif self.type == "mp4":
         resp = Response(data_iter, status=206)  # 状态码需设置为 206,否则无法拖动进度条
         resp.content_range = header.get('Content-Range', None)
     else:
         resp = Response(data_iter, status=200)
         resp.content_type = header.get('Content-Type', None)
     # 设置其它响应头的信息
     resp.content_length = header.get('Content-Length', None)
     return resp
예제 #4
0
    def return_video(self):

        with open(self.item.path) as file:
            file.seek(self.offset)
            data = file.read(self.count)
            byte_array = bytearray(data)

            response = Response('Partial Content')
            response.status_code = 206
            response.content_length = self.count
            response.content_range = 'bytes ' + self.content_range + '/' + self.file_size_in_str
            response.content_type = self.video_condition.mime
            response.data = byte_array

            return response
예제 #5
0
def avatar_v1(address):
    try:
        address = aioxmpp.JID.fromstr(address)
    except (ValueError, TypeError):
        return abort(400, "bad address")

    metadata = db.session.query(
        model.Avatar.hash_,
        model.Avatar.last_updated,
        model.Avatar.mime_type,
    ).filter(model.Avatar.address == address, ).one_or_none()

    if metadata is None:
        return abort(404, "no avatar stored")

    hash_, last_updated, mime_type = metadata

    response = Response(mimetype=mime_type)
    response.status_code = 500
    response.add_etag(hash_)
    response.last_modified = last_updated
    response.expires = datetime.utcnow() + CACHE_AVATAR_TTL
    response.headers["Content-Security-Policy"] = \
        "frame-ancestors 'none'; default-src 'none'; style-src 'unsafe-inline'"

    if (request.if_none_match.contains(hash_)
            or (request.if_modified_since is not None
                and last_updated <= request.if_modified_since)):
        response.status_code = 304
        return response

    if request.method == "HEAD":
        # do not fetch the data, only its size
        length, = db.session.query(sqlalchemy.func.length(
            model.Avatar.data), ).filter(
                model.Avatar.address == address).one()
        response.status_code = 200
        response.content_length = length
        return response

    data, = db.session.query(
        model.Avatar.data, ).filter(model.Avatar.address == address).one()

    response.data = data
    response.status_code = 200
    return response
예제 #6
0
def show_attachment(id):
    id = int(id)
    attach = Attachment.get_by_id(id)
    resp = Response(attach.content, mimetype='application/octet-stream')
    resp.content_length = attach.size
    filename = attach.filename
    try:
        filename = filename.encode('latin-1')
    except UnicodeEncodeError:
        filenames = {
            # 'filename': "UTF-8''{}".format(url_quote(filename)),
            'filename': "{}".format(url_quote(filename)),
        }
    else:
        filenames = {'filename': filename}
    resp.headers.set('Content-Disposition', 'attachment', **filenames)
    return resp
예제 #7
0
def send_file(fp, mimetype):
    try:
        fileno = fp.fileno()
        stat = os.stat(fileno)
    except OSError:
        stat = None

    resp = Response(
        wrap_file(request.environ, fp),
        mimetype=mimetype,
        direct_passthrough=True,
    )
    resp.cache_control.no_store = True
    if stat is not None:
        resp.cache_control.public = True
        resp.content_length = stat.st_size
        check = adler32(
            f"{stat.st_dev}:{stat.st_ino}".encode("ascii")) & 0xFFFFFFFF
        resp.set_etag(f"lektor-{stat.st_mtime}-{stat.st_size}-{check}")
    return resp
예제 #8
0
 def bad_range(self):
     response = Response('Range Not Satisfiable')
     response.status_code = 416
     response.content_range = 'bytes: */' + self.file_size_in_str
     response.content_length = 0
     return response