Custom name for uploaded file

2,258 views
Skip to first unread message

miroslavgojic

unread,
Nov 18, 2011, 3:03:48 PM11/18/11
to web2py-users
I have upload form, and it's work.
I use example from book.

But file get new name by web2py, can I control this name and how

on other words can I give my name for uploaded file.

Regards

Miroslav

Anthony

unread,
Nov 18, 2011, 3:54:12 PM11/18/11
to web...@googlegroups.com
web2py renames the file for security purposes, and to enable it to retrieve the file later via response.download. It encodes the original filename within the new filename and decodes it upon download. What exactly do you need to do?

Anthony

miroslavgojic

unread,
Nov 18, 2011, 4:28:33 PM11/18/11
to web2py-users
What I need to do? It is hard to explain but I will tray.

On my faculty I need to setup small web for professors and students.
Professors can upload files (*.pdf, and possibly some *.zip) and they
need to login for putting content - uploading files.
Filter is make like SELECT(OPTION(),OPTION()), and I have 4 SELECT (4
drop-down list)
From Select and options I use professor name and his id, subject name
and subject id ...
from professor.id and subject.id and some other parameters I need to
create file name...

example of my file name in upload folder:
professor.id_subject.id_year_number.pdf
number is some number like number of row in database or just simply ++
counter
year is current year, can be setup from list or from date()

The content is not confidential, now is on open FTP, just some
lectures from mathematics or other subjects.
We have problems with FTP, professors have problem to upload files on
FTP (ftp tools are complicated for them - some of professors are
old ...)

On student side I have multi apply filter, after students select list
options and apply filter they will get list of file for download.

I hope so that is understandable.

Miroslav

miroslavgojic

unread,
Nov 18, 2011, 5:55:59 PM11/18/11
to web2py-users
some questions:

Can I turnoff default changing name with upload function?

Can I before upload start, change file name (rename(from.first.name,
to.second.name)) and than proceed to upload...
User select file for upload, application first give new name to file
and than start upload with new name, and new name can be changed or
not from upload function.




On Nov 18, 9:54 pm, Anthony <abasta...@gmail.com> wrote:

Anthony

unread,
Nov 18, 2011, 6:40:25 PM11/18/11
to web...@googlegroups.com
On Friday, November 18, 2011 5:55:59 PM UTC-5, miroslavgojic wrote:
some questions:

Can I turnoff default changing name with upload function?

I don't think so. As an alternative, process the form with dbio=False so it doesn't do the upload or database insert, and then manually process the upload however you want and store your filename in the db. See http://web2py.com/book/default/chapter/07#SQLFORM-without-database-IO.

Anthony 

miroslavgojic

unread,
Nov 19, 2011, 2:53:13 AM11/19/11
to web2py-users
I reed all in online book about upload and forms...

Can I make my upload manually, something like: brows_file ->
upload_to_some_folder.
What is happening after I submit button 'upload' - can I have control
on this activity.

I'm new with Web2Py and Python, but on PHP this is no problem, I make
all my code upload form and files go to folders what I chose, and file
name is my will same or changed...
In Python I see some functions os.rename for renaming files, but it is
directly rename file name.

Can I have may custom upload form with two way
first: sending file to folder - no need for database
second: sending data to database - and don'n need to know is file or
something else.

On download process I can us something like list folder content and
make links for download (from file list and database data I will
generate links for download)

If you have doubts why so complicated, and why I don't use simply way
shown in book -> answer is: the chairman of department what that files
stored as early mentioned...

Miroslav

miroslavgojic

unread,
Nov 19, 2011, 3:37:03 AM11/19/11
to web2py-users
Hear is PHP example (to show what is my wish to do):

in HTML:
<html>
<body>

<form action="upload_file.php" method="post"
enctype="multipart/form-data">
<label for="file">Filename:</label>
<input type="file" name="file" id="file" />
<br />
<input type="submit" name="submit" value="Submit" />
</form>

</body>
</html>

in PHP file upload_file.php:
<?php
if ($_FILES["file"]["error"] > 0)
{
echo "Error: " . $_FILES["file"]["error"] . "<br />";
}
else
{
echo "Upload: " . $_FILES["file"]["name"] . "<br />";
echo "Type: " . $_FILES["file"]["type"] . "<br />";
echo "Size: " . ($_FILES["file"]["size"] / 1024) . " Kb<br />";
echo "Stored in: " . $_FILES["file"]["tmp_name"];
}
?>

Is this possible with Python and web2py?

Miroslav

miroslavgojic

unread,
Nov 19, 2011, 4:54:03 AM11/19/11
to web2py-users
What I have for now:

in view:
{{=form}}
{{=form_data}}

in controller:
import cgi

def upload():
form = FORM("Upload
file:",INPUT(_type='file',_name='myfile'),INPUT(_type='submit',_name='submit',_value='Submit'))
if form.accepts(request,session):
response.flash = 'form accepted'
elif form.errors:
response.flash = 'form has errors'
else:
response.flash = 'please fill the form'
form_data = cgi.FieldStorage()
file_data = form['myfile']
fp =open('some/file','wb') // this folder/file make some errors
fp.write(file_data)
fp.close()
return dict(form=form,file_data=file_data)

This is what I have for now...

Miroslav

Anthony

unread,
Nov 19, 2011, 8:50:14 AM11/19/11
to web...@googlegroups.com
Sure, you can code all that manually.


On Saturday, November 19, 2011 2:53:13 AM UTC-5, miroslavgojic wrote:
I reed all in online book about upload and forms...

Can I make my upload manually, something like: brows_file ->
upload_to_some_folder.
What is happening after I submit button 'upload' - can I have control
on this activity.

I'm new with Web2Py and Python, but on PHP this is no problem, I make
all my code upload form and files go to folders what I chose, and file
name is my will same or changed...
In Python I see some functions os.rename for renaming files, but it is
directly rename file name.

Can I have may custom upload form with two way
first: sending file to folder - no need for database
second: sending data to database - and don'n need to know is file or
something else.

On download process I can us something like list folder content and
make links for download (from file list and database data I will
generate links for download)

If you have doubts why so complicated, and why I don't use simply way
shown in book -> answer is: the chairman of department what that files
stored as early mentioned...

Miroslav

Anthony

unread,
Nov 19, 2011, 9:01:38 AM11/19/11
to web...@googlegroups.com
On Saturday, November 19, 2011 4:54:03 AM UTC-5, miroslavgojic wrote:
What I have for now:

in view:
{{=form}}
{{=form_data}}

No need for 'form_data' on the page (your controller doesn't return it anyway).
 

in controller:
import cgi

def upload():
    form = FORM("Upload
file:",INPUT(_type='file',_name='myfile'),INPUT(_type='submit',_name='submit',_value='Submit'))

    if form.accepts(request,session):
        response.flash = 'form accepted'
    elif form.errors:
        response.flash = 'form has errors'
    else:
        response.flash = 'please fill the form'
    form_data = cgi.FieldStorage()

No need for 'form_data'. When you upload the file, the field values are stored in request.vars and then transferred into form.vars. The file upload will be in form.vars.myfile, which will already be a cgi.FieldStorage() object. So, form.vars.myfile.file will be the open file object, and form.vars.myfile.filename will be the original name of the uploaded file.
 

    file_data = form['myfile']
    fp =open('some/file','wb') // this folder/file make some errors

It's generally best to use os.path.join to build file paths. Also, if you want to store the files within your application's folder, you should start at request.folder, which is the absolute path to the application folder:

import os
filepath = os.path.join(request.folder, 'path', 'to', 'myfile.ext')
 

    fp.write(file_data)
    fp.close()
    return dict(form=form,file_data=file_data)

Just return the form to the view -- handle everything else in the controller.
 
Anthony

miroslavgojic

unread,
Nov 19, 2011, 11:41:02 AM11/19/11
to web2py-users
> No need for 'form_data'. When you upload the file, the field values are
> stored in request.vars and then transferred into form.vars. The file upload
> will be in form.vars.myfile, which will already be a cgi.FieldStorage()
> object. So, form.vars.myfile.file will be the open file object, and
> form.vars.myfile.filename will be the original name of the uploaded file.

I have error in this

form.vars.myfile.filename
<type 'exceptions.AttributeError'>('str' object has no attribute
'filename')

form.vars.myfile.file
<type 'exceptions.AttributeError'>('str' object has no attribute
'file')

Miroslav

Anthony

unread,
Nov 19, 2011, 11:52:04 AM11/19/11
to web...@googlegroups.com
You might need to access the file before calling form.accepts (first you'll have to check that form.vars.myfile exists). You can also access it via request.vars.myfile (which won't change, even after form.accepts).

Anthony

miroslavgojic

unread,
Nov 19, 2011, 12:06:40 PM11/19/11
to web2py-users
The error is caused when file is not selected.
By default on first run form is empty (file is not selected), and form
must wait for selecting and submitting.

How access to file before calling form? What that mean?

Miroslav

Anthony

unread,
Nov 19, 2011, 12:12:11 PM11/19/11
to web...@googlegroups.com
You can tell if the function is being called with a form submission by checking for request.vars:

if request.vars:
    print 'this is a form submission'


On Saturday, November 19, 2011 12:06:40 PM UTC-5, miroslavgojic wrote:
The error is caused when file is not selected.
By default on first run form is empty (file is not selected), and form
must wait for selecting and submitting.

How access to file before calling form? What that mean?

Miroslav

miroslavgojic

unread,
Nov 19, 2011, 12:44:31 PM11/19/11
to web2py-users
Now I have in controller:

def upload():
form = FORM("Upload
file:",INPUT(_type='file',_name='myfile'),INPUT(_type='submit',_name='submit',_value='Submit'))
if request.vars:
if form.accepts(request,session):
my_file = request.vars.myfile.file
my_filename = request.vars.myfile.filename
filepath = os.path.join(request.folder, 'uploads') // this
path work - it is absolute path in hard drive
fp =open(filepath.my_filename,'wb')
fp.write(my_file)
fp.close()
return dict(form=form)

request.vars.myfile -> make return on stored object
request.vars.myfile.file -> make return address of stored object

I understood what you told me, and logical check on conditions, but
how to put everything in one function.

the pseudo algorithm in my head is next:

make def func():
make form = FORM(...)
check if condition existing
make file = request.vars.myfile.file
make filename = request.vars.myfile.filename
make filepath = os.path.join(...)
make write file to filepath filename
go to page and show empty form - wait for new file
else:
just show empty form without submission
return form

but I just loss my mind after 24 ours of trying this or similar
uploads.

Miroslav

Anthony

unread,
Nov 19, 2011, 1:24:44 PM11/19/11
to web...@googlegroups.com
Don't put the form.accepts inside the 'if request.vars' block -- it needs to run even on form creation (to generate the hidden formname and formkey fields).

On Nov 19, 6:12 pm, Anthony <abas...@gmail.com> wrote:
> You can tell if the function is being called with a form submission by
> checking for request.vars:
>
> if request.vars:
>     print 'this is a form submission'
>
>
>
>
>
>
>
> On Saturday, November 19, 2011 12:06:40 PM UTC-5, miroslavgojic wrote:
>
> > The error is caused when file is not selected.
> > By default on first run form is empty (file is not selected), and form
> > must wait for selecting and submitting.
>
> > How access to file before calling form? What that mean?
>
> > Miroslav
>

Miroslav Gojic

unread,
Nov 19, 2011, 2:14:26 PM11/19/11
to web...@googlegroups.com
Can I get full example for upload function?

This is maybe simply but after one day I don'n have any success.

- - Miroslav Gojic - -

Anthony

unread,
Nov 19, 2011, 4:36:30 PM11/19/11
to web...@googlegroups.com
Something like this:

def upload():
    import os
    uploadfolder=os.path.join(request.folder, 'uploads')
    form = SQLFORM.factory( 
        Field('file', 'upload', uploadfolder=uploadfolder),
        Field('new_name'))
    if form.process().accepted:
        os.rename(os.path.join(uploadfolder, form.vars.file),
            os.path.join(uploadfolder, form.vars.new_name))
    return dict(form=form)

The above uses SQLFORM.factory, though you could also do it using FORM. Rather than handling the upload completely manually, this code allows web2py to use its usual upload mechanism and automatic file naming, and then it simply renames the uploaded file to the name you want (this code allows you to enter the new filename in the form itself, though you could use some other mechanism for generating the name).

Note, because you're not storing the filename in a db table and not using the standard naming scheme, you won't be able to use the response.download() method for downloading, though it sounds like you don't need to. Instead, you can use response.stream() if necessary.

Anthony

Miroslav Gojic

unread,
Nov 20, 2011, 3:29:38 AM11/20/11
to web...@googlegroups.com
Thanks Anthony, upload it's work

Now I have some questions:
Can I use form.formstyle = 'divs' on form created with SQLFORM.factory or some other methods to get div tag instead table

what is difference between:
if form.process().accepted:
and
if form.accepts(request,session):


If I have two variables (var1 and var2)
var1 = Object 
var2 = cStringIO.StrindO 0x1234

Before your example I was stack with 
file.write(var1)
or
file.write(var2)
write() - can write only string // this was error message

how I can get string value from var1=Object or var2=cStringIO.StrindO
on net I find that I need to do serialization 
on python that is pickle (if I am not wrong)

On var1 or var2 actually is file what I need to upload
but I don't need to get values from file in string I need file from var1 or var2 send or save or write to folder
in os I look on os.save() but I'm not shoure is that good way

if I have file in some variable how I can that file save to folder?


- - Miroslav Gojic - -


Massimo Di Pierro

unread,
Nov 20, 2011, 11:50:35 AM11/20/11
to web2py-users
> what is difference between:
> if form.process().accepted:
> and
> if form.accepts(request,session):

no difference functionally, just different APIs.

> If I have two variables (var1 and var2)
> var1 = Object
> var2 = cStringIO.StrindO 0x1234
>
> Before your example I was stack with
> file.write(var1)
> or
> file.write(var2)

> how I can get string value from var1=Object or var2=cStringIO.StrindO

file.write(var2.read())

or more memory efficiently

import shutil
shutil.copyfileobj(var2,file)


Miroslav Gojic

unread,
Nov 20, 2011, 5:28:08 PM11/20/11
to web...@googlegroups.com
This is code for manual upload (it's work for me):

def upload():
    import os
    import shutil
    uploadfolder=os.path.join(request.folder, 'uploads')
    form = FORM(
        "Upload file:",
        INPUT(_type='file',_name='my_file', requires=IS_NOT_EMPTY()),
        'Your name:',
        INPUT(_name='new_name', requires=IS_NOT_EMPTY()),
        INPUT(_type='submit'))
    if form.process(dbio=True).accepted:
        m_ofn = form.vars.my_file.filename
        m_nf = uploadfolder + '/' + m_ofn + '_' + form.vars.new_name
        my_object = form.vars.my_file.file
        m_f = open(m_nf, "wb")
        #m_f.write(my_object.read()) //this ca be used 
        shutil.copyfileobj(my_object,m_f) //but I us this
        m_f.close()
    return dict(form=form)

Thanks to Anthony and Massimo


- - Miroslav Gojic - -



Reply all
Reply to author
Forward
0 new messages