To solve this data typing problem I converted everything to string type
so when sending the response to the browser it is sent with data type
in bytes, it worked for status code, header, text message, except for
the file type of image where I change the min-type to ( image/png ),
but no visibility in the browser of the .png file ?
Just converting everything to str via arbitrary methods is not the
correct way to fix your probems. It only hides them or pushes the side
effects further away from where you’re doing things (for example, by
sending junk data to a browser which doesn’t render it).
You’ve gone:
self.s_file = str(self.b_file, "utf-8")
This DOES NOT do what you seem to imagine. This claims that b_file is a
bytes object which encodes some text in utf-8. And then deocdes it. I
am astonished that this did not result in a UnicodeDecodeError exception
for you - you must have been very lucky with your image file data, which
by chance must resemble utf-8 data, at least in terms of being a legal
sequence of bytes for utf-8. There’s every chance this should fail.
Unless your test file is maybe empty. Example:
>>> str(b'abc\x81', 'utf-8')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x81 in position 3: invalid start byte
This is not what you should be doing.
There are 2 approaches which are valid:
- what I suggested, which is to conduct the HTTP response in bytes
entirely
- your approach, to conduct it as though HTTP were text
If you choose the latter you need to encode the binary data as text in
a form which the receiving browser can decode. For example, base64.
First, let’s be clear about what you’re doing above: you are taking
binary bytes and trying to decode them as though they contain utf-8
encoded text, to get some text. FOr image data, that is nonsense, even
if the decode succeeds - it is not text and the decode is not
meaningful. Then you’re passing that text (str) to request.sendall().
That method then encodes the text in some fashion which you have not
specified in order to send bytes over the wire. Your decode step is
nonsense and the encode step in unspecified.
If you’re going to try to pretend the HTTP transaction is text, you want
to choose a text encoding of the binary data. That invlves two steps:
- convert the binary data to a text form such as base64, for example
using the base64.b64encode() function
- include a Content-Transfer-Encoding header to indicate to the
receiving client that the data are in base64 form; note that this
still returns a bytes object, but you can encode that as a str using
ASCII. (This would let you join everything use as str, it just seems a
little pointless because request.sendall() is just going to be
reversing that to send things over the network.)
Cheers,
Cameron Simpson cs@cskk.id.au