Skip to main content

AJAX File Upload with Web2py

It was not that long, since I experienced a problem while trying to upload a file using an ajax  trapped form. I thought, it must be me doing something wrong. I was using web2py to embed another page into a page via ajax. That is better known to web2py folk as LOADing a component.

It's just happened that one of such component contains a file upload form. It was my first time using LOAD function provided by web2py. Basically it make use of jQuery to load the page via ajax into a target div and traps input of any form in that page, so that page doesn't reload. Oh, I forgot to say that web2py is bundled with jQuery.

It's always boring and tedious to understand a problem without experiencing it. So, Let's play with an example, (PS: I"m using web2py a full stack python framework, but you can use any language at server side and this problem will be there because, it's a problem with ajax)

My model which defines table like this,



In RDBMS world, it column 'file' of table 'image' will transformed to a type of CHAR(or VARCHAR) and column must not be empty (notnull)
Web2py can enforce this at many levels.
notnull = True is enforced by database
required = True is enforced by DAL (database abstraction layer) of web2py
requires = IS_NOT_EMPTY() is enforced by SQLFORM.
You are free to use any of them and it's up to you to use all of them or only one of them. (we give choice :-) )


Now, the index function which maps a url and renders output



As you see web2py automates almost everything (yes, you can customize everything, and do it manually, if you want). This code generate an upload form as per database table IMAGE. automatically upload file into database, and if there's errors shows them to the user. After successful upload page is redirected to /upload/default/index.html. Wow, Magick! :-)

Now go to myform.html > You will be greeted with a file upload form and it just work.

OK, now we decided to embed myform.html into another page(say index.html).

For that we wrote {{=LOAD(URL(c='default', f='myform.load'))}} in index.html and it got transformed to:



for non-web2py folks, URL function generate url, and here .load is served with a content type of text/html. By using .load extension page is rendered without any template we set up for regular html display. The url /example/default/myform.load is of course a relative url, it get interpreted as http://xyz.com/upload/component/index.load. Here 'example' is application, 'default' is controller and myform is a function. ie., http://xyz.com/example/default/myform.load will map to a function called myform() in a file default.py in an application called example and rendered based on extension(.load, .html, .json, .xml etc).

I can't figure out what's going on. It always showed an error message stating that file is empty.
And I fire up my browser's developer plugins and it become clear that file is not being sent to server via ajax. Yes, it's because ajax can't sent files (read XMLHTTP object).

There are two remedies for this (as far as I can think of)
1) use an iframe to load component. Since there is no AJAX there, it'll work.
this is as simple as writing {{=IFRAME(_src=URL(c='default', f='myform.load'))}} in your view. (here index.html).

But, I hate iframe you may say (whether you say it or not, I'll). I learned a lesson in past that users care about functionality and not a bit about whether we use this or that and follows standard. So, I'm ready to break some if that cause better usability. (So I used iframe). Don't be disappointed, I have another option for you folks,

2) Use one of many ajax file upload plugins. I am going to show a solution based on uploadify library. It uses swfupload. and jQuery. So, if you really want to avoid iframe and burden users by making them download few more dependencies download uploadify library and extarct it into your server. (That said, this library is great if you want to implement multi-file upload). By using uploadify, you are going to do DB insert yourself. (if that's OK go ahead). Extract uploadify download into a folder called 'uploadify' under static directory.

change myform function to:




However, I tried it without embedding into another page, but it'll work even if it's embedded.
There are many different plugins available to do the same, each differs in their approach(like submitting form to an embed iframe.
So take your time to find them and go through them. (So server side code may change depending on your library of choice).
Please look these libraries:

  1. valums ajax upload
  2. jQuery Form plugin


Happy experimentations  :)

Comments

  1. Hi, if I set "auto" option = false, have this error:
    AttributeError: 'NoneType' object has no attribute 'file'. How fix it?

    ReplyDelete
  2. It had been months since I wrote this.


    A possible cause for error might be erroneous ajax calls that the library is making.
    Can you open firebug and give the failed request url&params for auto=false, and succes request url&params for good scenario.

    then I can better help you.

    ReplyDelete

Post a Comment

Popular posts from this blog

My First Python Program

I am very glad today. Because I finally wrote a python program all by myself. I am programming for about 3 years. Of which 2 are using C++ (Old standard and using Turbo C++ IDE ver 3.0 and yet to master Templates and STL. [:-p]) and After starting python using Dive into Python an excellent book by Mark Pilgrim during my 1st year summer vacation, and I only completed Data Structure section. Then I found an excellent Java tutorial by Sang Shin and obtained a certificate by completing First and basic course in Java. Now I am working with My Friend to develop applications in java. We established a web site already. He started programming when he is in 10, ie. more than 2 years of experience. He has Visual Basic too in his side. Now he is doing with JSP and I am concentrating on Python, Ruby (yet to start) and CSS. Today My pleasure is that I completed a python program myself. Which is asked to do in ' A byte of Python ' by Swaroop.C.H. Which is a command line program; and he...

Start on Microchip programming... for hobby or for money

One of my friend asked me today the following question,  I'm often asked about this, someway or other. Let me answer this now for all.... Q: " I want to start programming on chip.. Can you suggest a good chip and a device to program it? Also tell me any sites which can help me ." A:" Simple one is Arduino. You will get it packaged with a programmer. If you want some more powerful and commercial one, Go for Microchip's PIC family of processors. After you are familiar with those, and need even more power, try AVR from ATMEL ." Some resources from my Bookmarks is given below: http://www.voti.nl/swp/ http://www.embedds.com/ http://www.instructables.com/id/Business-Card-PIC-Programmer/step2/Parts/ http://www.arduino.cc/playground/Main/ElectroInfoResources http://www.piclist.com/techref/microchip/index.htm My bookmarks become so messy now a days, and I'm not getting time to organize them. So, these are the quickest ones that I pic...