1. 程式人生 > >Stream a file with tornado

Stream a file with tornado

現在手機上的空間往往不夠,所以影片最好就是直接連到server 上透過串流回來看就好了,在tornado 上串流的 demo:

class StaticFileHandler(RequestHandler):

Alright this time I found the actual solution:

            # Note: only return HTTP 206 if less than the entire range has been
            # requested. Not only is this semantically correct, but Chrome
# refuses to play audio if it gets an HTTP 206 in response to # ``Range: bytes=0-``.

This note applies to audio only, chrome will play video that begins be returning a 206.

    @asynchronous
    @gen.coroutine
    def get(self, path, include_body=True):
        #Assume that path is correct, validation will be handeled elsewhere
self.absolute_path = os.path.abspath(path) self.path = self.absolute_path if self.absolute_path is None: return self.modified = self.get_modified_time() self.set_headers() if self.should_return_304(): self.set_status(304
) return request_range = None range_header = self.request.headers.get("Range") if range_header: # As per RFC 2616 14.16, if an invalid Range header is specified, # the request will be treated as if the header didn't exist. request_range = httputil._parse_request_range(range_header) if request_range: start, end = request_range size = self.get_content_size() if (start is not None and start >= size) or end == 0: # As per RFC 2616 14.35.1, a range is not satisfiable only: if # the first requested byte is equal to or greater than the # content, or when a suffix with length 0 is specified self.set_status(416) # Range Not Satisfiable self.set_header("Content-Type", "text/plain") self.set_header("Content-Range", "bytes */%s" % (size, )) return if start is not None and start < 0: start += size if end is not None and end > size: # Clients sometimes blindly use a large range to limit their # download size; cap the endpoint at the actual file size. end = size self.set_status(206) # Partial Content self.set_header("Content-Range", httputil._get_content_range(start, end, size)) else: start = end = None content = self.get_content(self.absolute_path, start, end) for chunk in content: self.write(chunk) yield gen.Task(self.flush) self.finish()