Problems with file uploading using FORM

57 views
Skip to first unread message

Maurice Ling

unread,
May 25, 2017, 11:34:44 AM5/25/17
to web2py-users, lingw...@gmail.com
Hi everyone,

I am stuck with an issue - please refer to the code below.

1. I have a form (new_entry function)  that I will like to use to be able to upload a file among other fields.
2. I am using FORM instead of SQLFORM because one of the dropdown fields (line 11) in the form is generated at run time.
3. The way that I did was to use input file type (line 9) to open a file selection browser / window to select the file - this works OK.
4. If form.vars.uploadfile is not empty, it means that a file had been selected for uploading.
5. I will the want to copy the file into application/<app name>/upload folder using shutils (lines 17-25) but the file name will be changed to entry.file.<random number>.<original file name>
6. However, this does not work as I get the error that the file is not found.
7. For debugging, I print the source file name (line 21) and it only gave me the file name when I will need the entire file path for shutil.copy2() at line 25 to work.

Can someone assist?

Any help will be greatly appreciated.

Thank in advance and warm regards

Maurice Ling

  1. def new_entry():
  2.     if session.username == None: redirect(request.env.http_referer + "account/log_in")
  3.     # get unarchived notebooks
  4.     else:
  5.         notebook = [notebook['name'] for notebook in cydb(cydb.notebook.archived == False).select(cydb.notebook.name)]
  6.         notebook.sort()
  7.         form = FORM(TABLE(
  8.                 TR('Title: ', INPUT(_type='text', _name='title', _size=80)),
  9.                 TR('File: ', INPUT(_type='file', _name='uploadfile')),
  10.                 TR('tags: ', INPUT(_type='text', _name='tags', _size=80)),
  11.                 TR('Notebook: ', SELECT(notebook, _name='notebook')),
  12.                 TR('Description: ', TEXTAREA(_type='text', _name='description'),
  13.                 TR('',INPUT(_type='submit', _name='SUBMIT')))))
  14.         if form.accepts(request.vars, session):
  15.             notebook = cydb(cydb.notebook.name == form.vars.notebook).select(cydb.notebook.id).as_list()[0]['id']
  16.             if form.vars.uploadfile != '':
  17.                 # upload file into applications/<app name>/upload folder
  18.                 import os, random, shutil
  19.                 upload_dir = os.sep.join([os.getcwd(), 'applications', request.application, 'uploads'])
  20.                 sourcefile = form.vars.uploadfile.filename
  21.                 print sourcefile
  22.                 newfile = upload_dir + os.sep + 'entry.file.' + \
  23.                         str(int(random.random()*10000000000000)) + \
  24.                         os.path.splitext(sourcefile)[-1]
  25.                 shutil.copy2(sourcefile, newfile)
  26.                 cydb.ent.insert(title=form.vars.title,
  27.                                  author=session.username,
  28.                                  notebook=notebook_id,
  29.                                  tags=form.vars.tags,
  30.                                  file=newfile.split(os.sep)[-1],
  31.                                  filename=newfile.split(os.sep)[-1],
  32.                                  description=form.vars.description)
  33.             else:
  34.                 # no file to upload
  35.                 cydb.ent.insert(title=form.vars.title,
  36.                                  author=session.username,
  37.                                  notebook=id,
  38.                                  tags=form.vars.tags,
  39.                                  file='',
  40.                                  filename='',
  41.                                  description=form.vars.description)
  42.             bb.tape.insert(event='New entry created. %s. Title = %s'% \
  43.                             (cydb(cydb.notebook.id==notebook_id).select(cydb.notebook.name),
  44.                             form.vars.title),
  45.                         user=session.username)
  46.             response.flash='your entry has been successfully added'
  47.         return dict(form=form)

Dave S

unread,
May 25, 2017, 2:55:50 PM5/25/17
to web2py-users, lingw...@gmail.com


On Thursday, May 25, 2017 at 8:34:44 AM UTC-7, Maurice Ling wrote:
Hi everyone,

I am stuck with an issue - please refer to the code below.

[...]
5. I will the want to copy the file into application/<app name>/upload folder using shutils (lines 17-25) but the file name will be changed to entry.file.<random number>.<original file name>
6. However, this does not work as I get the error that the file is not found.
7. For debugging, I print the source file name (line 21) and it only gave me the file name when I will need the entire file path for shutil.copy2() at line 25 to work.
[...]
               sourcefile = form.vars.uploadfile.filename
  1.                 print sourcefile
  2.                 newfile = upload_dir + os.sep + 'entry.file.' + \
  3.                         str(int(random.random()*10000000000000)) + \
  4.                         os.path.splitext(sourcefile)[-1]
  5.                 shutil.copy2(sourcefile, newfile)
[...]
 
A browser won't tell you the path to the file, just the filename.  It's a security measure.  The shutil.copy2() call can only handle files local to the server.  If you're using this page locally on the server, then you can provide the path information through other channels.

I do something like this on my home machine, because I'm using my app to tag my photos.   Currently, I provide a text field on the form to enter path (separate from filename), but I check that path against a list I keep in the code.  That limits the amount filesystem exploration someone could do if they somehow got access to my app.
(BTW, drag-and-drop works for getting the filename into its field).

/dps


Maurice Ling

unread,
Jun 9, 2017, 1:03:57 PM6/9/17
to web2py-users, lingw...@gmail.com
Thanks for your reply, Dave.

However, I don't really get the part on "drag and drop" - do you mean drag and drop the file into the field? Will it work for a text area?

Please kindly elaborate.

Thank you once again,
Maurice

Dave S

unread,
Jun 9, 2017, 4:04:13 PM6/9/17
to web2py-users, lingw...@gmail.com

On Friday, June 9, 2017 at 10:03:57 AM UTC-7, Maurice Ling wrote:
Thanks for your reply, Dave.

However, I don't really get the part on "drag and drop" - do you mean drag and drop the file into the field? Will it work for a text area?

It works with an upload field, which is what you need for uploading a file.  Part of the story is HTML5, and part is javascript, but it already works in web2py with all modern browsers.  The app that expects pictures is at home, so I can't look at thumbnails, but I just tested it with another app here.  Client was W10 (but should be able to go back to at least XP), Firefox 53.0.3, but should work back into the 30s.  To do the test, I opened the page with form, switched windows to WinExplorer to select a file, left-clicked on the one I chose, and dragged it over the "Browse..." button for the upload field.

On  the server side, I log the upload activity (beyond what Rocket puts into httpserver.log) which at the moment includes the size of the file and the id of upload table row.

/dps

Reply all
Reply to author
Forward
0 new messages