RE: [Zope] External methods and images
i think what you're seeing is the by-now-infamous ExternalMethod exception-handling bug (tm). ExternalMethod is seeing an exception in some part of the external method. in processing that exception, it assumes the exception type is a string, which it almost never is. this usually causes a second exception in the exception-handling code, which kills the function (and produces the traceback you see). i was able to patch it by replacing line 255 in ExternalMethod.py with: ----- if (type(error_type) is type('')) and (lower(error_type) in ('redirect',)): ----- i know less than nothing about the version control system, or even the bug reporting system (please forgive me, i'm only marginally competent with the systems we use here in-house) so i haven't made the change above "official" in any way. if someone could take care of that, i'd appreciate it. -----Original Message----- From: Tony McDonald [mailto:tony.mcdonald@ncl.ac.uk] Sent: Friday, May 07, 1999 8:50 AM Hi, I have an external method that gets an image from a directory (ie the image is *not* in the ZODB) and then adds the correct headers to display it to the browser. Trouble is, it don't work. anyone got any ideas? This is driving me batty.
i think what you're seeing is the by-now-infamous ExternalMethod exception-handling bug (tm). ExternalMethod is seeing an exception in some part of the external method. in processing that exception, it assumes the exception type is a string, which it almost never is. this usually causes a second exception in the exception-handling code, which kills the function (and produces the traceback you see).
i was able to patch it by replacing line 255 in ExternalMethod.py with:
----- if (type(error_type) is type('')) and (lower(error_type) in ('redirect',)): -----
i know less than nothing about the version control system, or even the bug reporting system (please forgive me, i'm only marginally competent with the systems we use here in-house) so i haven't made the change above "official" in any way. if someone could take care of that, i'd appreciate it.
Ah, that might explain it. Only problem is that I'm using Zope-1.11.0pr1 and there aren't enough lines in ExternalMethod.py All I really want to do is pass the name of an image to an external method which then extracts it from a directory, wraps it up in the content-type magic and sends it back to me. Does anyone have something like it working? Any pointers gratefully received. TIA Tone ------ Dr Tony McDonald, FMCC, Networked Learning Environments Project The Medical School, Newcastle University Tel: +44 191 222 5888 Fingerprint: 3450 876D FA41 B926 D3DD F8C3 F2D0 C3B9 8B38 18A2
On Mon, 10 May 1999, Tony McDonald wrote:
i think what you're seeing is the by-now-infamous ExternalMethod exception-handling bug (tm). ExternalMethod is seeing an exception in some part of the external method. in processing that exception, it assumes the exception type is a string, which it almost never is. this usually causes a second exception in the exception-handling code, which kills the function (and produces the traceback you see).
i was able to patch it by replacing line 255 in ExternalMethod.py with:
----- if (type(error_type) is type('')) and (lower(error_type) in ('redirect',)): -----
i know less than nothing about the version control system, or even the bug reporting system (please forgive me, i'm only marginally competent with the systems we use here in-house) so i haven't made the change above "official" in any way. if someone could take care of that, i'd appreciate it.
Ah, that might explain it. Only problem is that I'm using Zope-1.11.0pr1 and there aren't enough lines in ExternalMethod.py
All I really want to do is pass the name of an image to an external method which then extracts it from a directory, wraps it up in the content-type magic and sends it back to me. Does anyone have something like it working? Any pointers gratefully received.
Well, haven't got it working... haven't even tested it, but my guess would be attach the content-type header as plain-text to the front of your return value. The syntax of the content-type header should be in any CGI manual. I think that when you access an external method directly it acts very like CGI, in that the ZPublisher returns it without any preparatory wrapping. So I think you need to put the header in manually. Good luck.
TIA Tone ------ Dr Tony McDonald, FMCC, Networked Learning Environments Project The Medical School, Newcastle University Tel: +44 191 222 5888 Fingerprint: 3450 876D FA41 B926 D3DD F8C3 F2D0 C3B9 8B38 18A2
_______________________________________________ Zope maillist - Zope@zope.org http://www.zope.org/mailman/listinfo/zope
(For developer-specific issues, use the companion list, zope-dev@zope.org - http://www.zope.org/mailman/listinfo/zope-dev )
-- Howard Clinton Shaw III - Grum St. Thomas High School #include <disclaimer.h>
All I really want to do is pass the name of an image to an external method which then extracts it from a directory, wraps it up in the content-type magic and sends it back to me. Does anyone have something like it working? Any pointers gratefully received.
Well, haven't got it working... haven't even tested it, but my guess would be attach the content-type header as plain-text to the front of your return value. The syntax of the content-type header should be in any CGI manual. I think that when you access an external method directly it acts very like CGI, in that the ZPublisher returns it without any preparatory wrapping. So I think you need to put the header in manually. Good luck.
Thanks for the thoughts. I've got something very similar to that, in that at the top level of the Zope tree, I have an external method called 'img'. The code is here; def img(self, src, RESPONSE): import os img_dir = '/home/zope/Zope-1.11.0pr1-src/Images' typemap={'.gif' : 'image/gif', '.jpg' : 'image/jpeg'} img_name=os.path.join(img_dir, src) # Determine the ad type # img_type=self.image_type(img_name) img_ext = img_name[-4:] img_type = typemap[img_ext] # Open ad file, using 'rb' to open it in binary mode! img_file=open(img_name, 'rb') img_data=img_file.read() img_file.close() # Set the content-type of the response RESPONSE.setHeader('content-type', img_type) return img_data The Images directory has a file in it called s1cb.gif If I access the image so http://server/img?src=s1cb.gif I get an image on the browser. If I use the following DTML, <!--#var "img(src='s1cb.gif')"--> I get a TypeError. I also get it with <!--#var "img('s1cb.gif')"--> It gets weirder though... If I use <!--#var "img('s1cb_p0000001.gif', RESPONSE)"--> however, I get a document downloaded to the desktop that has rendered HTML *and* what looks like binary data (it's certainly got GIF89A embedded in it) where the DTML was placed. Ok, so what am I doing wrong? (answers on a postcard please) TIA tone ------ Dr Tony McDonald, FMCC, Networked Learning Environments Project The Medical School, Newcastle University Tel: +44 191 222 5888 Fingerprint: 3450 876D FA41 B926 D3DD F8C3 F2D0 C3B9 8B38 18A2
At 10:53 11/05/99 , Tony McDonald wrote:
Thanks for the thoughts.
I've got something very similar to that, in that at the top level of the Zope tree, I have an external method called 'img'. The code is here; def img(self, src, RESPONSE): import os img_dir = '/home/zope/Zope-1.11.0pr1-src/Images' typemap={'.gif' : 'image/gif', '.jpg' : 'image/jpeg'}
img_name=os.path.join(img_dir, src)
# Determine the ad type # img_type=self.image_type(img_name) img_ext = img_name[-4:] img_type = typemap[img_ext]
# Open ad file, using 'rb' to open it in binary mode! img_file=open(img_name, 'rb') img_data=img_file.read() img_file.close()
# Set the content-type of the response RESPONSE.setHeader('content-type', img_type) return img_data
The Images directory has a file in it called s1cb.gif
If I access the image so http://server/img?src=s1cb.gif I get an image on the browser.
If I use the following DTML, <!--#var "img(src='s1cb.gif')"--> I get a TypeError. I also get it with <!--#var "img('s1cb.gif')"-->
It gets weirder though... If I use <!--#var "img('s1cb_p0000001.gif', RESPONSE)"--> however, I get a document downloaded to the desktop that has rendered HTML *and* what looks like binary data (it's certainly got GIF89A embedded in it) where the DTML was placed.
Ok, so what am I doing wrong? (answers on a postcard please)
Your external method returns the binary image, while the <!--#var--> tag expects data it can include into a _textual_ document. DTML Methods and Documents should return a textual format, not binairy image data. To include an image into a HTML document, you can best give the URL of your external method to the browser, like so: <IMG SRC="/img?src=s1cb.gif"> The browser will then request that URL from the server, and will get the image, wich it will place into it's proper place in the rendered HTML document. -- Martijn Pieters, Web Developer | Antraciet http://www.antraciet.nl | Tel: +31-35-6254545 Fax: +31-35-6254555 | mailto:mj@antraciet.nl http://www.antraciet.nl/~mj | PGP: http://wwwkeys.nl.pgp.net:11371/pks/lookup?op=get&search=0xA8A32149 ------------------------------------------
Your external method returns the binary image, while the <!--#var--> tag expects data it can include into a _textual_ document. DTML Methods and Documents should return a textual format, not binairy image data.
To include an image into a HTML document, you can best give the URL of your external method to the browser, like so:
<IMG SRC="/img?src=s1cb.gif">
The browser will then request that URL from the server, and will get the image, wich it will place into it's proper place in the rendered HTML document.
-- Martijn Pieters, Web Developer
Oh...mi....gawd. It works. Beautifully. I need to go back and read the Zope Docs again (and then again). I'm using <!--#var xyz--> far too much it seems. Many many thanks Martijn, I think you've helped a rather large lightbulb go off in my nut. Cheers again. Tone. ------ Dr Tony McDonald, FMCC, Networked Learning Environments Project The Medical School, Newcastle University Tel: +44 191 222 5888 Fingerprint: 3450 876D FA41 B926 D3DD F8C3 F2D0 C3B9 8B38 18A2
Tony McDonald writes:
Ah, that might explain it. Only problem is that I'm using Zope-1.11.0pr1 and there aren't enough lines in ExternalMethod.py
All I really want to do is pass the name of an image to an external method which then extracts it from a directory, wraps it up in the content-type magic and sends it back to me. Does anyone have something like it working? Any pointers gratefully received.
TIA Tone
I have played with external methods to get a gallery going. I wrap the uploaded file from the REQUEST into a subclass of File. The loading looks like this: def em_addpic(self, REQUEST): """\ Add a picture object to the local folder, represented by (self) """ try: pname = REQUEST['title'] mapped_name = get_uni_id(pname) fobj=GalleryPic(mapped_name, pname, REQUEST['file'], content_type=_ftype(pname)) fobj._set_descr(REQUEST['descr']) fobj._mk_thumb() # Should be called from __init__ self._setObject(mapped_name, fobj) except: import sys return sys.exc_type, sys.exc_value if REQUEST is not None: return MessageDialog(title='Picture added to Gallery.', message='Picture %s added to Gallery.' % (pname,), action='%s/showgal' % REQUEST['URL1'] ) _ftype is taken from the fsimport.py external method, it looks only for the extension of pname in a dictionary, if you know the content type then it would be easy. GalleryPicis the subclass of File, it holds a reference to an external picture and puts a thumbnail into the database. Look into the File class. The actual data is wrapped into a class, which can be used to read from the filesystem. HTH, __Janko
participants (5)
-
Howard Clinton Shaw III -
jhauser@ifm.uni-kiel.de -
Martijn Pieters -
Tony McDonald -
Wolf Logan