(request, response, path, type=None, disposition=None,
               name=None)
return response
Set status, headers, and body in order to serve the given file.

    The Content-Type header will be set to the type arg, if provided.
    If not provided, the Content-Type will be guessed by the file extension
    of the 'path' argument.

    If disposition is not None, the Content-Disposition header will be set
    to "<disposition>; filename=<name>". If name is None, it will be set
    to the basename of path. If disposition is None, no Content-Disposition
    header will be written.
Set status, headers, and body in order to serve the given file.
Set status headers and body in order to serve the given file .
def serve_file(request, response, path, type=None, disposition=None,
               name=None):
    """Set status, headers, and body in order to serve the given file.

    The Content-Type header will be set to the type arg, if provided.
    If not provided, the Content-Type will be guessed by the file extension
    of the 'path' argument.

    If disposition is not None, the Content-Disposition header will be set
    to "<disposition>; filename=<name>". If name is None, it will be set
    to the basename of path. If disposition is None, no Content-Disposition
    header will be written.
    """

    if not os.path.isabs(path):
        raise ValueError("'%s' is not an absolute path." % path)

    try:
        st = os.stat(path)
    except OSError:
        return notfound(request, response)

    # Check if path is a directory.
    if stat.S_ISDIR(st.st_mode):
        # Let the caller deal with it as they like.
        return notfound(request, response)

    # Set the Last-Modified response header, so that
    # modified-since validation code can work.
    response.headers['Last-Modified'] = formatdate(
        st.st_mtime, usegmt=True
    )

    result = validate_since(request, response)
    if result is not None:
        return result

    if type is None:
        # Set content-type based on filename extension
        ext = ""
        i = path.rfind('.')
        if i != -1:
            ext = path[i:].lower()
        type = mimetypes.types_map.get(ext, "text/plain")
    response.headers['Content-Type'] = type

    if disposition is not None:
        if name is None:
            name = os.path.basename(path)
        cd = '%s; filename="%s"' % (disposition, name)
        response.headers["Content-Disposition"] = cd

    # Set Content-Length and use an iterable (file object)
    #   this way CP won't load the whole file in memory
    c_len = st.st_size
    bodyfile = open(path, 'rb')

    # HTTP/1.0 didn't have Range/Accept-Ranges headers, or the 206 code
    if request.protocol >= (1, 1):
        response.headers["Accept-Ranges"] = "bytes"
        r = get_ranges(request.headers.get('Range'), c_len)
        if r == []:
            response.headers['Content-Range'] = "bytes */%s" % c_len
            return httperror(request, response, 416)
        if r:
            if len(r) == 1:
                # Return a single-part response.
                start, stop = r[0]
                r_len = stop - start
                response.status = 206
                response.headers['Content-Range'] = (
                    "bytes %s-%s/%s" % (start, stop - 1, c_len)
                )
                response.headers['Content-Length'] = r_len
                bodyfile.seek(start)
                response.body = bodyfile.read(r_len)
            else:
                # Return a multipart/byteranges response.
                response.status = 206
                boundary = _make_boundary()
                ct = "multipart/byteranges; boundary=%s" % boundary
                response.headers['Content-Type'] = ct
                if "Content-Length" in response.headers:
                    # Delete Content-Length header so finalize() recalcs it.
                    del response.headers["Content-Length"]

                def file_ranges():
                    # Apache compatibility:
                    yield "\r\n"

                    for start, stop in r:
                        yield "--" + boundary
                        yield "\r\nContent-type: %s" % type
                        yield ("\r\nContent-range: bytes %s-%s/%s\r\n\r\n"
                               % (start, stop - 1, c_len))
                        bodyfile.seek(start)
                        yield bodyfile.read(stop - start)
                        yield "\r\n"
                    # Final boundary
                    yield "--" + boundary + "--"

                    # Apache compatibility:
                    yield "\r\n"
                response.body = file_ranges()
        else:
            response.headers['Content-Length'] = c_len
            response.body = bodyfile
    else:
        response.headers['Content-Length'] = c_len
        response.body = bodyfile

    return response
def serve_file ( request , response , path , type = None , disposition = None , name = None ) : if not os . path . isabs ( path ) : raise ValueError ( "'%s' is not an absolute path." % path ) try : st = os . stat ( path ) except OSError : return notfound ( request , response ) # Check if path is a directory. if stat . S_ISDIR ( st . st_mode ) : # Let the caller deal with it as they like. return notfound ( request , response ) # Set the Last-Modified response header, so that # modified-since validation code can work. response . headers [ 'Last-Modified' ] = formatdate ( st . st_mtime , usegmt = True ) result = validate_since ( request , response ) if result is not None : return result if type is None : # Set content-type based on filename extension ext = "" i = path . rfind ( '.' ) if i != - 1 : ext = path [ i : ] . lower ( ) type = mimetypes . types_map . get ( ext , "text/plain" ) response . headers [ 'Content-Type' ] = type if disposition is not None : if name is None : name = os . path . basename ( path ) cd = '%s; filename="%s"' % ( disposition , name ) response . headers [ "Content-Disposition" ] = cd # Set Content-Length and use an iterable (file object) #   this way CP won't load the whole file in memory c_len = st . st_size bodyfile = open ( path , 'rb' ) # HTTP/1.0 didn't have Range/Accept-Ranges headers, or the 206 code if request . protocol >= ( 1 , 1 ) : response . headers [ "Accept-Ranges" ] = "bytes" r = get_ranges ( request . headers . get ( 'Range' ) , c_len ) if r == [ ] : response . headers [ 'Content-Range' ] = "bytes */%s" % c_len return httperror ( request , response , 416 ) if r : if len ( r ) == 1 : # Return a single-part response. start , stop = r [ 0 ] r_len = stop - start response . status = 206 response . headers [ 'Content-Range' ] = ( "bytes %s-%s/%s" % ( start , stop - 1 , c_len ) ) response . headers [ 'Content-Length' ] = r_len bodyfile . seek ( start ) response . body = bodyfile . read ( r_len ) else : # Return a multipart/byteranges response. response . status = 206 boundary = _make_boundary ( ) ct = "multipart/byteranges; boundary=%s" % boundary response . headers [ 'Content-Type' ] = ct if "Content-Length" in response . headers : # Delete Content-Length header so finalize() recalcs it. del response . headers [ "Content-Length" ] def file_ranges ( ) : # Apache compatibility: yield "\r\n" for start , stop in r : yield "--" + boundary yield "\r\nContent-type: %s" % type yield ( "\r\nContent-range: bytes %s-%s/%s\r\n\r\n" % ( start , stop - 1 , c_len ) ) bodyfile . seek ( start ) yield bodyfile . read ( stop - start ) yield "\r\n" # Final boundary yield "--" + boundary + "--" # Apache compatibility: yield "\r\n" response . body = file_ranges ( ) else : response . headers [ 'Content-Length' ] = c_len response . body = bodyfile else : response . headers [ 'Content-Length' ] = c_len response . body = bodyfile return response