"Unable to handle upload" error when manually adding an entry for a file dropped into TinyMCE

108 views
Skip to first unread message

Boa

unread,
Jan 3, 2016, 12:35:54 PM1/3/16
to web...@googlegroups.com

I'm getting the Exception "<type 'exceptions.RuntimeError'> Unable to handle upload" when attempting to insert a file uploaded with the TinyMCE text editor into a DB table. The TinyMCE editor allows the user to drag and drop image files directly into the editing window, for upload. Upon form submission, BeautifulSoup parses out the image files, and an attempt is made to enter the images into the DB manually. The image files are being created on the system's disk, and stored as expected, but the DB entry cannot be added. Here's the setup:

Model:

     db.define_table('t_image',
       
Field('f_story_id', type='reference t_story',      # each image is associated with an article
              label
= current.T('Story Id')),
       
Field('f_image_file', type='upload', uploadseparate = True,
              uploadfolder
=os_path_join(self.request.folder,'uploads'),
              requires
=IS_EMPTY_OR(IS_IMAGE(error_message=current.T("Please use a JPEG, PNG, or BMP that is 1024x1024 or less"),
                                   maxsize
= (1024, 1024), extensions=('jpeg','jpg','png','bmp','gif'))),
              label
=current.T('File')),
       
# a bunch of other fields are defined
       
)

The following function is called when the form containing TinyMCE is validated, and it attempts to insert the images:

def insert_images_for_new_story(story_id, form):
   
from StringIO import StringIO
   
from base64 import b64decode, urlsafe_b64decode, decodestring

    soup
= BeautifulSoup(form.vars.tinymce_textarea, 'html5')    # BS's default 'lxml' parser CANNOT be used!
   
   
for idx, img in enumerate(soup.findAll('img')):                          # examine all the images
        dict__img
= {'f_story_id':story_id,
                    
'f_index': idx, 'f_image_caption': img['alt'] if img.has_attr('alt') else None,
                    
'f_height': int(img['height']) if img.has_attr('height') else None,
                    
'f_width': int(img['width']) if img.has_attr('width') else None}
       

        # if image is not a file upload, do nothing  
       
if not img['src'].startswith('data:image'):      
           
continue

       
# create an appropriate filename
        image_type
= img['src'].split(',',1)[0].rsplit('image/', 1)[1].rsplit(';',1)[0]
        filename
= '%s_%s.%s' % (form.vars.f_title.replace(' ','_'), idx, image_type)

       
# create StringIO object from image
        # the image source is something like:
"data:image/jpeg;base64,..."
        b64decoded_img
= b64decode(img['src'].split(',',1)[1])
        image_file_buffer
= StringIO(b64decoded_img)
       
        # perform image insert
        id__image
= db.t_image.insert(f_image_file = db.t_image.f_image_file.store(file = image_file_buffer, filename = filename),
                                     
**dict__img)

        tag__image_placeholder
= soup.new_tag('imgplaceholder', idx = idx)        # replace image tag with a placeholder
        img
.replace_with(tag__image_placeholder)

   
return str(soup)        # return the updated html code

The error is being produced in the DAL's  _attempt_upload() function at line 708: https://github.com/web2py/pydal/blob/master/pydal/objects.py#L708

In _attempt_upload(), the "value" variable is equal to the name of the file which is to be inserted, and 'fields' is showing up as:

{'f_height': None, 'f_index': 0, 'is_active': True, 'created_on': datetime.datetime(2016, 1, 3, 11, 58, 15, 780000), 'modified_on': datetime.datetime(2016, 1, 3, 11, 58, 15, 780000), 'modified_by':<function lazy_user at 0x000000000B0639E8>, 'f_image_caption': u'', 'f_width': None, 'f_image_file': u't_image.f_image_file.ab85d264c7896c21.53746f72795f3853746f72795f385f302e6a706567.jpeg', 'created_by': <function lazy_user at 0x000000000B0639E8>, 'f_story_id': 4L}

I'd greatly appreciate suggestions on how to resolve the issue that's causing the error. Thanks!

Boa

unread,
Jan 3, 2016, 10:54:53 PM1/3/16
to web...@googlegroups.com
Problem solved (?): it seems the .store() function returns a unicode object instead of a string, and unicode can't be inserted into the DB as the filename. It can be fixed by casting the unicode text as a string:

db.t_image.insert(f_image_file = str(db.t_image.f_image_file.store(file = image_file_buffer, filename = filename)), **dict__img)

That brings up the question - is it a desirable behavior for .store() to return unicode?
Reply all
Reply to author
Forward
0 new messages