CGI python 3 write RAW BINARY

D

Dodo

Help! this is driving me crazy lol
I want to print raw binary data to display an image file
BUT
python3 outputs b'<binary data>' instead of <binary data>.... so the
browser can't read the image!!

f = open("/some/path/%s" % x, 'rb')
print(f.read())



any idea?
Dorian
 
G

Gary Herron

Dodo said:
Help! this is driving me crazy lol
I want to print raw binary data to display an image file
BUT
python3 outputs b'<binary data>' instead of <binary data>.... so the
browser can't read the image!!

f = open("/some/path/%s" % x, 'rb')
print(f.read())



any idea?
Dorian


Huh??? In what universe does printing raw binary data display an image?

But it that's what you want -- don't use print (which formats objects
for human reading), and don't use standard output (which is a text
stream in Python3). Instead, open your own stream in binary mode, and
write (not print) to that stream.
 
A

Antoine Pitrou

Le Wed, 28 Apr 2010 23:54:07 +0200, Dodo a écrit :
Help! this is driving me crazy lol
I want to print raw binary data to display an image file BUT
python3 outputs b'<binary data>' instead of <binary data>.... so the
browser can't read the image!!

f = open("/some/path/%s" % x, 'rb')
print(f.read())

print() implicitly converts its arguments to str (i.e. unicode strings)
and then writes them to sys.stdout, which is a text IO wrapper.
If you want to bypass the unicode layer, you have to use
sys.stdout.buffer instead.
That is:

sys.stdout.buffer.write(f.read())

Regards

Antoine.
 
D

Dodo

Le 29/04/2010 01:45, Antoine Pitrou a écrit :
Le Wed, 28 Apr 2010 23:54:07 +0200, Dodo a écrit :


print() implicitly converts its arguments to str (i.e. unicode strings)
and then writes them to sys.stdout, which is a text IO wrapper.
If you want to bypass the unicode layer, you have to use
sys.stdout.buffer instead.
That is:

sys.stdout.buffer.write(f.read())

Regards

Antoine.

@Gary : How do I reply to a http request then?

@Antoine : It not sys.stdout.buffer.write but sys.stdout.write()
instead. But it still doesn't work, now I have empty content

#!/usr/bin/python3
import cgi, os, sys
form = cgi.FieldStorage()
all = os.listdir("/some/path/with/files/")
for x in all:
if x.find( form['id'].value ) != -1:
ext = x.split(".")[-1]
print("Content-type:image/%s\n\n" % ext)
f = open("/some/path/with/files/%s" % x, 'rb')
sys.stdout.write( f.read() )
f.close()
break

Dorian
 
A

Antoine Pitrou

Le Thu, 29 Apr 2010 12:53:53 +0200, Dodo a écrit :
@Antoine : It not sys.stdout.buffer.write but sys.stdout.write()
instead. But it still doesn't work, now I have empty content

Let me insist: please use sys.stdout.buffer.write().
You'll also have to call sys.stdout.flush() before doing so.
 
D

Dodo

Le 29/04/2010 17:07, Antoine Pitrou a écrit :
Le Thu, 29 Apr 2010 12:53:53 +0200, Dodo a écrit :

Let me insist: please use sys.stdout.buffer.write().
You'll also have to call sys.stdout.flush() before doing so.
Oh, I tested on my windows machine avec sys.stdout.buffer.write() didn't
work.
I just tested on my linux server, and it works....

So, let's modify the script

sys.stdout.buffer.write( f.read() )
sys.stdout.flush()

Now I have:
malformed header from script. Bad header=ÿØÿà: show.py
and it tells me Internal Server error :(

I can't see the error messages (traceback)
any idea to do so?

Dorian
 
A

Antoine Pitrou

Le Thu, 29 Apr 2010 18:33:08 +0200, Dodo a écrit :
Oh, I tested on my windows machine avec sys.stdout.buffer.write() didn't
work.
I just tested on my linux server, and it works....

So, let's modify the script

sys.stdout.buffer.write( f.read() )
sys.stdout.flush()

Sorry, I should have been clearer. You have to flush sys.stdout before
using sys.stdout.buffer, such that the unicode layer doesn't keep any
unwritten data. So this should be:

sys.stdout.flush()
sys.stdout.buffer.write( f.read() )

Regards

Antoine.
 
D

Dodo

Le 29/04/2010 22:21, Antoine Pitrou a écrit :
Le Thu, 29 Apr 2010 18:33:08 +0200, Dodo a écrit :

Sorry, I should have been clearer. You have to flush sys.stdout before
using sys.stdout.buffer, such that the unicode layer doesn't keep any
unwritten data. So this should be:

sys.stdout.flush()
sys.stdout.buffer.write( f.read() )

Regards

Antoine.

.....I don't get a thing.
Now with the fix :
All browsers shows a different thing, but not the image!
http://ddclermont.homeip.net/misc/python/

If I save it to computer :
* Windows image viewer won't read it
* Irfanview can read it without problems

Dorian

PS : ça commence sérieusement à m'énerver
 
D

Dodo

Le 29/04/2010 18:33, Dodo a écrit :
Le 29/04/2010 17:07, Antoine Pitrou a écrit :
Oh, I tested on my windows machine avec sys.stdout.buffer.write() didn't
work.
I just tested on my linux server, and it works....

So, let's modify the script

sys.stdout.buffer.write( f.read() )
sys.stdout.flush()

Now I have:
malformed header from script. Bad header=ÿØÿà: show.py
and it tells me Internal Server error :(

I can't see the error messages (traceback)
any idea to do so?

Dorian

Ok, I just checked, the CRC of the file in the server is not the same
the in the browser
I don't understand how the data could be modified...

Dorian
 
A

Antoine Pitrou

Le Thu, 29 Apr 2010 23:37:32 +0200, Dodo a écrit :
....I don't get a thing.
Now with the fix :
All browsers shows a different thing, but not the image!
http://ddclermont.homeip.net/misc/python/

If I save it to computer :
* Windows image viewer won't read it
* Irfanview can read it without problems

Did you set the content-type and content-length in the HTTP headers?
Can you post your code?
 
D

Dodo

Le 30/04/2010 17:52, Antoine Pitrou a écrit :
Le Thu, 29 Apr 2010 23:37:32 +0200, Dodo a écrit :

Did you set the content-type and content-length in the HTTP headers?
Can you post your code?
I didn't know about content-lenght
Here's the new code (I used a fixed image patch to make sure this is not
the source of the problem)


#!/usr/bin/python3
import cgi, sys, cgitb
cgitb.enable()

f = open("/home/dodo/54.jpg", "rb")
data = f.read()
l = len(data)
f.close()

print("Content-type:image/jpg\nContent-length:%d\n\n" % l)

sys.stdout.flush()
sys.stdout.buffer.write( data )



Dorian
 
G

Gabriel Genellina

Le 30/04/2010 17:52, Antoine Pitrou a écrit :
I didn't know about content-lenght
Here's the new code (I used a fixed image patch to make sure this is not
the source of the problem)


#!/usr/bin/python3
import cgi, sys, cgitb
cgitb.enable()

f = open("/home/dodo/54.jpg", "rb")
data = f.read()
l = len(data)
f.close()

print("Content-type:image/jpg\nContent-length:%d\n\n" % l)

sys.stdout.flush()
sys.stdout.buffer.write( data )

Computers are dumb. You have to speak to them very slow and clearly in
order to be understood :)

You need a space after those ':'. The correct media type for JPEG images
is image/jpeg. And (the important thing) you have one more \n than
necessary. Each header field finishes with \n; an empty line (just \n)
marks the end of all headers; the body [your image] must follow
immediately.

#!/usr/bin/python3
import cgi, sys, cgitb
cgitb.enable()

f = open("/home/dodo/54.jpg", "rb")
data = f.read()
l = len(data)
f.close()

print("Content-Type: image/jpeg\nContent-Length: %d\n" % l)

sys.stdout.flush()
sys.stdout.buffer.write( data )

(Probably, a better way would be to replace all those \n with \r\n, and
not use print at all, but the above code is good enough).
 
D

Dodo

Le 01/05/2010 12:52, Dodo a écrit :
Le 30/04/2010 17:52, Antoine Pitrou a écrit :

I didn't know about content-lenght
Here's the new code (I used a fixed image patch to make sure this is not
the source of the problem)


#!/usr/bin/python3
import cgi, sys, cgitb
cgitb.enable()

f = open("/home/dodo/54.jpg", "rb")
data = f.read()
l = len(data)
f.close()

print("Content-type:image/jpg\nContent-length:%d\n\n" % l)

sys.stdout.flush()
sys.stdout.buffer.write( data )



Dorian
Anyone?
 
S

sam

Le 01/05/2010 12:52, Dodo a écrit :












Anyone?

Yes for windows you need to call this before you write it out. And
yes its totally retarded that you have to do this. The whole point of
python is that I don't have to worry about the particular system its
running on.

def __SetStdOutForWindowsToBinaryMode():
# Without this method a windows server will translate '\n'
into '\r\n'
# even for binary output. This probably isn't needed on linux
servers
# so the exception will be caught harmlessly.
# At some point we may have to worry about switching this mode
*back* to original
# (see http://bytes.com/topic/python/answers/30987-cgi-proplem-displaying-image)
try:
import msvcrt,os
msvcrt.setmode( 1, os.O_BINARY ) # 1 = stdout; use 0 for
stdin
except ImportError:
pass
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,763
Messages
2,569,562
Members
45,038
Latest member
OrderProperKetocapsules

Latest Threads

Top