Hello again,
What does the autodelete function use to locate files? I seem to have
broken mine.
Cheers,
-James
On Thursday, April 11, 2013 12:01:11 PM UTC+12, James Burke wrote:
>
> Here's what I came up with. Perhaps not such a great solution, because it
> pigeon holes my download function.... But it works =)
>
> model/client.py
>
> def store_file(file, filename=None, path=None, client_dir=None, sub_folder
> =None):
> if sub_folder == 'Workbench':
> path = "D:/DATA_EXTRACTS/%s/Scripts" %(client_dir)
> else:
> path = "D:/DATA_EXTRACTS/%s/Scripts/%s" %(client_dir, sub_folder)
>
> if not os.path.exists(path):
> os.makedirs(path)
> pathfilename = os.path.join(path, filename)
> dest_file = open(pathfilename, 'wb')
> try:
> shutil.copyfileobj(file, dest_file)
> finally:
> dest_file.close()
>
>
> filename = '%s/%s/%s' %(client_dir,sub_folder,filename)
> return filename
>
>
>
>
> def retrieve_file(filename, path=None):
> file_path = filename.split('/')
> if file_path[1] == 'Workbench':
> path = "D:/DATA_EXTRACTS/%s/Scripts" %(file_path[0])
> else:
> path = "D:/DATA_EXTRACTS/%s/Scripts/%s" %(file_path[0], file_path[1])
> filename = file_path[2]
> return (filename, open(os.path.join(path, filename), 'rb'))
>
>
> db.define_table('file',
> Field('client', 'reference client'),
> Field('type', requires=IS_IN_SET(['Clipper','Workbench', 'Terramatch',
> 'Supply']), default='Workbench'),
> Field('file', type='upload',
> custom_store=lambda file,filename,path: store_file(file, filename, path,
> db.client(request.vars.client).client_dir_name if request.vars.client
> else None,
> request.vars.type if request.vars.type else None),
> custom_retrieve=lambda filename, path: retrieve_file(filename, path)),
> Field('sequence', 'integer', required=True),
> Field('created_date', 'datetime', default=request.now,
> readable=False,writable
> =False),
> Field('modified_date', 'datetime', update=request.now,
> readable=False,writable
> =False),
> format='%(file)s')
>
>
>
> controller/default.py
> def download():
> if not request.args:
> raise HTTP(400)
> name = "%s/%s/%s" %(request.args[0],request.args[1],request.args[2])
> field = db["file"]["file"]
>
>
> try:
> (filename, file) = field.retrieve(name)
> except IOError:
> raise HTTP(404)
> response.headers["Content-Disposition"] = "attachment; filename=%s"
> %request
> .args[-1]
> stream = response.stream(file, chunk_size=64*1024, request=request)
> raise HTTP(200, stream, **response.headers)
>
> Solution modified from:
> http://stackoverflow.com/questions/8008213/web2py-upload-with-original-filename/8185933#8185933
>
>
>
> On Tuesday, April 9, 2013 11:47:59 PM UTC+12, Anthony wrote:
>>
>> Another option -- when submitting a form, the value for db.file.client
>> should be in request.vars.client, so you could do:
>>
>> custom_store=lambda file, filename, path: store_file(file, filename, path
>> ,
>> db.client(request.vars.client).client_dir_name if request.vars.client
>> else None)
>>
>> You will also need to fetch the client id in custom_retrieve, though that
>> will be trickier because it won't be in request.vars in that case. Instead,
>> I would recommend you include the custom directory name within the filename
>> created by custom_store -- so custom_store would create a filename like
>> table.field.folder.uuid_fragment.encoded_filename.ext. Then your
>> custom_retrieve function could simply extract the directory name from the
>> filename. In fact, in that case, you don't need an entire custom_retrieve
>> function -- instead, you can just implement a
>> custom_retrieve_file_properties function (see
>> https://code.google.com/p/web2py/source/browse/gluon/dal.py#9355 for
>> what that function is supposed to return). That way, when retrieving the
>> file, you don't need the client id, and you avoid an unnecessary database
>> query to get the directory name (which is already available in the
>> filename).
>>
>> Anthony
>>
>> On Monday, April 8, 2013 11:26:09 PM UTC-4, James Burke wrote:
>>>
>>> Came up with a workaround.
>>> def store_file(file, filename=None, path=None):
>>> try:
>>> client_id = int(request.args[2])
>>> client_dir = db(db.client.id == client_id).select(db.client.
>>> client_dir_name).first().client_dir_name
>>> except:
>>> client_dir = 'Default'
>>>
>>> path = "applications/init/uploads/%s" % (client_dir)
>>> if not os.path.exists(path):
>>> os.makedirs(path)
>>> pathfilename = os.path.join(path, filename)
>>> dest_file = open(pathfilename, 'wb')
>>> try:
>>> shutil.copyfileobj(file, dest_file)
>>> finally:
>>> dest_file.close()
>>>
>>>
>>> return filename
>>>
>>> I'm using a smartgrid so the client id is passed as an argument when I
>>> client on the files link.
>>>
>>> On Tuesday, April 9, 2013 2:34:35 PM UTC+12, James Burke wrote:
>>>>
>>>> Thanks for your swift response.
>>>>
>>>> I kind of understand that, but how do you get the value rather than the
>>>> field name?
>>>>
>>>> db.define_table('file',
>>>> Field('client', 'reference client'),
>>>> Field('type', requires=IS_IN_SET(['Clipper','Workbench', 'Terramatch',
>>>> 'Supply']), default='Workbench'),
>>>> Field('file', type='upload',
>>>> custom_store=lambda file,filename,path: store_file(file, filename,path
>>>> , db.file.client._id),
>>>> custom_retrieve=lambda filename, path: retrieve_file(filename, path,db
>>>> .file.client)),
>>>> format='%(file)s')
>>>>
>>>> I'm trying to retrieve the clients name and use it to generate the
>>>> folder.
>>>>
>>>> Cheers,
>>>>
>>>> -James
>>>>
>>>>
>>>> On Tuesday, April 9, 2013 2:06:54 PM UTC+12, Anthony wrote:
>>>>>
>>>>> The fourth argument passed to store_file() is db.table.new_filename,
>>>>> which is a DAL Field object. Your code is treating it as a string, and
>>>>> "table.new_filename" is the string representation of a Field object. If
>>>>> you
>>>>> want to include an actual filename string, then that's what you have to
>>>>> pass to the function.
>>>>>
>>>>> Anthony
>>>>>
>>>>> On Monday, April 8, 2013 9:34:45 PM UTC-4, James Burke wrote:
>>>>>>
>>>>>> Hi Anthony,
>>>>>>
>>>>>> I've tried the solution you've posted below:
>>>>>> Field('file', 'upload',
>>>>>> custom_store=lambda file, filename, path: store_file(file,filename
>>>>>> , path, db.table.new_filename),
>>>>>> ...)
>>>>>>
>>>>>> But when my additional parameter gets sent to store_file it sends
>>>>>> 'table.new_filename'
>>>>>>
>>>>>> def store_file(file, filename=None, path=None, new_filename=None):
>>>>>> path = "applications/init/uploads/%s" % (new_filename)
>>>>>> if not os.path.exists(path):
>>>>>> os.makedirs(path)
>>>>>> pathfilename = os.path.join(path, filename)
>>>>>> dest_file = open(pathfilename, 'wb')
>>>>>> try:
>>>>>> shutil.copyfileobj(file, dest_file)
>>>>>> finally:
>>>>>> dest_file.close()
>>>>>>
>>>>>>
>>>>>> return filename
>>>>>>
>>>>>> Results in a new folder in uploads called 'table.new_filename'
>>>>>>
>>>>>> Cheers
>>>>>> -James
>>>>>>
>>>>>> On Wednesday, August 8, 2012 11:51:44 PM UTC+12, Anthony wrote:
>>>>>>>
>>>>>>> On Wednesday, August 8, 2012 7:09:37 AM UTC-4, Jim Gregory wrote:
>>>>>>>>
>>>>>>>> Can custom_store and custom_retrieve take parameters when they are
>>>>>>>> called using Field, e.g.:
>>>>>>>> db.define_table('table',
>>>>>>>> Field('file', 'upload', custom_store=store_file(file,
>>>>>>>> db.table.new_filename),
>>>>>>>> custom_retrieve=retrieve_file(db.table.new_filename))?
>>>>>>>> Field('new_filename','string')
>>>>>>>> )
>>>>>>>>
>>>>>>>
>>>>>>> These attributes have to be callables, so you can't call them
>>>>>>> yourself. To pass additional custom arguments to a callable, just turn
>>>>>>> it
>>>>>>> into a lambda that takes the standard arguments and pass the additional
>>>>>>> arguments to your function within the lambda:
>>>>>>>
>>>>>>> Field('file', 'upload',
>>>>>>> custom_store=lambda file, filename, path: store_file(file,filename
>>>>>>> , path, db.table.new_filename),
>>>>>>> ...)
>>>>>>>
>>>>>>> When web2py calls the custom_store callable, it will pass three
>>>>>>> arguments (file, filename, and path), so your lambda must take three
>>>>>>> arguments. Within the lambda, you can then do whatever you want. You
>>>>>>> can
>>>>>>> pass any or all of the standard three arguments to your custom
>>>>>>> function,
>>>>>>> and you can pass additional arguments. In the example above, I passed
>>>>>>> the
>>>>>>> three standard arguments followed by a fourth custom argument, though
>>>>>>> it
>>>>>>> doesn't have to look like that (presumably you will at least want to
>>>>>>> pass
>>>>>>> the file as an argument).
>>>>>>>
>>>>>>> custom_retrieve takes two standard arguments, "name" and "path".
>>>>>>>
>>>>>>> Anthony
>>>>>>>
>>>>>>>
--
---
You received this message because you are subscribed to the Google Groups
"web2py-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.