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.


Reply via email to