pythonwsgiref

Broken image when serving it over HTTP


I came across a problem reading image files (.png, .jpg, .jpeg ...) where I get the following error in the terminal: UnicodeDecodeError: the 'utf-8' codec cannot decode the 0x89 byte in position 0 : invalid starting byte. I thought I had solved the problem just by declaring o_file = open ("cloud.png", "rb") because I no longer receive the error in the terminal but an error in viewing the file (cloud.png) according to the example below:

from wsgiref.simple_server import make_server

def hello_world_app(environ, start_response):

    i_file = open("cloud.png", "rb")
    o_file = i_file.read()

    status = '200 OK'  # HTTP Status
    headers = [("Content-type", "image/png; charset=utf-8")]
    start_response(status, headers)

    # The returned object is going to be printed
    return [str(o_file).encode("utf-8")]

with make_server('', 8000, hello_world_app) as httpd:

    print(
        'Running Kosmos Application\n'
        'Browser Access - http://127.0.0.1:8000\n'
        'Crl+c for flow command or Crl+z for stop'
    )
    # Serve until process is killed
    httpd.serve_forever()

enter image description here

I would like to know why this happens and how do I solve this problem without using a third party module? Below is a preview of the file normally opened without the use of python:

enter image description here


Solution

  • You seem to be severely confused about what character encodings are useful for.

    Probably read Joel Spolsky's The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!) before you try to read the rest of this answer.

    You are replacing the binary PNG data with mojibake when you encode it. You should not be manipulating the data at all; just read it into a buffer, and send it to the client. End of story.

    def hello_world_app(environ, start_response):
        with open("cloud.png", "rb") as i_file:
            o_file = i_file.read()
    
        status = '200 OK'  # HTTP Status
        headers = [("Content-type", "image/png")]  # no ; charset here!
        start_response(status, headers)
    
        return [o_file]