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
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
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
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
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
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
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
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