Forum Moderators: coopster

Message Too Old, No Replies

PHP file upload - progress indicator solution

describes potential architecure of PHP progress indicator for file uploads

         

rdkls

3:14 am on Apr 16, 2003 (gmt 0)



I haven't implemented this yet.
Thus far it is just an architectural description (i.e. no real 'code').
Difficulty level is medium/hard, but it's nothing you can't get skooled-up on given a few days work.

Situation

  1. Form with <input type="file">
  2. User submits form, sending HTTP request (mime-encoded as "multipart/form-data") to web server. This request contains the file data.
  3. File data received by php (writes to disk or whatever)

Problem
Want a progress indicator to continuously display how much of the file has been uploaded.

Solution
First - this is much easier in ASP since ASP has built-in support for reading chunks of HTTP requests (which contain the file data) as they come in. AFAIK, PHP is only invoked by the web server once the entire HTTP request (hence all file data) has been received.

Hence it is necessary to intercept the HTTP request before it gets to PHP i.e. at the web-server level.
This will be achieved by writing an apache module/hook (in perl) that is executed by the web server when a file upload begins.

Items required
----------------------------

  1. mod_perl upload hook
    (I've not used these before, knowledge incomplete)
    This is perl code that will get run by the web server when the user starts uploading file data.
    Uses the perl subclass "Apache::Request" to read (in chunks) the incoming data, and writes it to disk (in a temporary file).
    It records the location of the temporary file in the database so that the progress meter can constantly check it.
  2. php upload form script - generates the upload form
  3. php progress indicator page - generates the progress indicator (e.g. growing bar)
  4. php receive page (receives file uploads) - reads file data. Normally then writes to database/disk.
  5. database (I used mysql) with table :
    upload( uploadID int AUTO_INCREMENT, filenameSpool varchar, totalBytes int, dateBegun datetime, sessionID int)

Sequence of solution
----------------------------
1. user requests upload form

2. php upload form script executes
a. gets unique uploadID from database
The uploadIDs, if left unchecked, will increment out of control. To control this we delete the upload row when we're done, and just in case this hasn't worked, delete entries older than a few days when we start. Then reset the auto_increment to max( uploadID). This method won't keep uploadIDs perfectly as tight as they could be, but will generally control them.

  • delete from upload table where dateBegun is older than a few days (housekeeping)
  • select max(id) from upload
  • alter table upload AUTO_INCREMENT = (max id)
    This will have no effect if a record has since been input, but the majority of times it will - so long as it generally keeps the IDs at a reasonable level.
  • uploadID = insert into upload (uploadID, dateBegun, session_id())
    (if fail, go back to ii)

b. outputs form to user, containing uploadID in a hidden field.

3. user submits form to receive page
a. javascript launches progress indicator page (passing uploadID as GET variable)

4. mod_perl hook invoked

5. mod_perl hook processes upload request
a. updates database : (uploadID, spool file name, totalBytes)
b. starts writing file to disk (/tmp)

6. php progress indicator page continues to refresh
(always passes uploadID to itself)
a. from database, select filenameSpool, totalBytes where uploadID = $uploadID
b. get size of spool file
c. print page depicting proportion of actual file size : total bytes
d. if file doesn’t exist, or total size = uploaded size, set opening window’s location to be the ‘file uploaded’ page (fileList for the current folder I’m guessing)

7. php receive page invoked by web server
a. select filenameSpool, filename, sessionID from upload where uploadID = $_REQUEST[ ‘uploadID’]
b. check $row[ ‘sessionID’] = session_id() (for security - stops naughty users from swapping uploadIDs)
c. moves file to correct location/filename
d. delete from upload where uploadID = $uploadID

Phew, think that's it. Feedback most welcome.

DrDoc

3:39 am on Apr 16, 2003 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Welcome [webmasterworld.com] to Webmaster World!

Now, this sounds really interesting! I will be looking forward to see what others might have to say on this topic.