Hi Rudy

Have you tried re-defining the download function to include the path to the
location you have used for storing the uploaded files? For example, in my
case I ended up with the following in my controller:

def download():
    import os
     file_path = os.path.join(request.folder,'uploads', str(auth.user.client
), request.args(0))
     return response.stream(open(file_path), attachment=False, chunk_size=
4096)



Obviously you need to edit file_path in the above to match your situation.

Andy

On Sunday, October 8, 2017 at 9:28:21 PM UTC+3, Rudy wrote:
>
> Hi Andy / Anthony,
>
> May i ask how you have addressed the multi-tenant requirement separating 
> all those uploaded files from different tenant to keep track of their 
> storage usage.
>
> I want to use the client id as part of the uploadfolder, it worked as a 
> test below when I defined the uploadfolder in db.py with hardcoded 
> client_id. In reality, the client_id varies (is there a way to specify the 
> table company's id in the uploadfolder in db.py?), I thought of specifying 
> the uploadfolder info in the action where I would do my upload 
> (edit_company()), I could upload it but not download. 
>
> Is it the same issue as Anthony mentioned (for test purpose, i used the 
> same edit_company()'s SQLFORM to upload and download? i thought it would 
> execute the line 
> db.company.logo.uploadfolder=os.path.join(request.folder,'uploads', 
> str(company_id)) before it executes  form=SQLFORM(db.company, 
> record=record, deletable=True, showid=True, 
> upload=URL('download')).process(), obviously i missed out some 
> fundamental concept (no i didn't understand why Andy couldn't specify the 
> table definition in the module as SQLFORM and view.html would be executed 
> after calling attachment_module.define_tables()). Any insight will be much 
> appreciated.
>
> in db.py
> client_id=3 #hard coded here for illustration
> db.define_table('company',
> Field('logo', 'upload', label='Company Logo', 
>  uploadfolder=os.path.join(request.folder, 'uploads', client_id), 
> uploadseparate=True, autodelete=True))
>
> in default.py
> def edit_company():
>     company_id = request.args(0)
>     record=db.company(company_id)
>     db.company.logo.uploadfolder=os.path.join(request.folder,'uploads', 
> str(company_id))
>     db.company.chop.uploadfolder=os.path.join(request.folder,'uploads', 
> str(company_id))
>     form=SQLFORM(db.company, record=record, deletable=True, showid=True, 
> upload=URL('download')
>                  ).process()
>     if form.accepted:
>         session.flash='Info: you have updated your company details!!'
>         redirect(URL('manage_company'))
>     elif form.errors:
>         response.flash='Error: inside edit_company, form raised error!!'
>     else:
>         pass
>     return locals()
>
> On Monday, May 9, 2016 at 10:29:00 PM UTC+8, Andy W wrote:
>>
>> I have a multi-tenant application, where users can upload files. I save 
>> these in a different directory for each client (tenant), so I can keep tabs 
>> on the overall disk space and number of files uploaded by each.
>>
>> This works fine when the table is defined in a model file - from the view 
>> I can download existing files and upload new ones:
>>
>> Model:
>> from gluon import *
>> import os
>> client_id=3 #hard coded here for illustration
>>            
>> db.define_table('attachment_model',
>>     Field('attached_file', 'upload', label="Upload new file", 
>>           uploadfolder=os.path.join(request.folder, 'uploads', str(
>> client_id), 'attachments'),
>>           requires=IS_NOT_EMPTY(), autodelete=True),
>>     Field('filename', type='string', length=150, writable=False),
>>     migrate=True)
>>
>> Controller:
>> def model_based():
>>     db.attachment_model.filename.readable=False
>>     form_attachment=SQLFORM(db.attachment_model,
>>                  autodelete=True, labels=None, deletable=True,
>>                  fields=['attached_file'], submit_button='Attach file')
>>     if hasattr(request.vars.attached_file, "filename"):
>>         #save original file name
>>         form_attachment.vars.filename=request.vars.attached_file.filename
>>     if form_attachment.process().accepted:
>>         response.flash = 'attachment saved'
>>     elif form_attachment.errors:
>>         response.flash = 'form has errors'
>>     # list existing attachments
>>     rows=db(db.attachment_model.id>0).select()
>>     response.view = 'attachment.html'
>>     return dict(form_attachment=form_attachment,
>>                 rows=rows)
>>
>> View:
>> {{extend 'layout.html'}}
>> <h1>
>>     Attached files
>> </h1>
>>     <table class="table-striped">
>>         <thead>
>>             <tr>
>>                 <td>id</td>
>>                 <td>filename</td>
>>             </tr>
>>         </thead>
>>         <tbody>
>>             {{for r in rows:}}
>>                 <tr>
>>                     <td>{{=r.id}}</td>
>>                     <td>{{=A(r.filename, _href=URL('download', args=(str(
>> client_id) + '/attachments/' + r['attached_file'])))}}</td>
>>                 </tr>
>>             {{pass}}
>>         </tbody>
>>     </table>
>>     
>> <h2>Add new attachment</h2>
>> <div class="form-inline well">
>>     {{=form_attachment}}
>> </div>
>>
>> My issue is when I re-write the above so the model definition is moved to 
>> a module.
>>
>> Module mod_attachment.py:
>> from gluon import *
>> import os
>>
>> class Attachment_module(object):
>>     def __init__(self, db):
>>         self.db = db
>>
>>     def define_tables(self):
>>         db = self.db
>>         client_id=3
>>         if not 'attachment_module' in db.tables:
>>             db.define_table('attachment_module',
>>                 Field('attached_file', 'upload', label="Upload new file", 
>>                       uploadfolder=os.path.join(current.request.folder, 
>> 'uploads', str(client_id), 'attachments'), 
>>                       requires=IS_NOT_EMPTY(), autodelete=True),
>>                 Field('filename', type='string', length=150, writable=
>> False),
>>                 Field('request_tenant', type='integer', default=client_id
>> ,
>>                       readable=False, writable=False),
>>                 migrate=True)
>>
>> Revised controller:
>> def module_based():
>>     from mod_attachment import Attachment_module
>>     attachment_module = Attachment_module(db) 
>>     attachment_module.define_tables()
>>     db.attachment_module.filename.readable=False
>>     form_attachment=SQLFORM(db.attachment_module,
>>                  autodelete=True, labels=None, deletable=True,
>>                  fields=['attached_file'], submit_button='Attach file')
>>     if hasattr(request.vars.attached_file, "filename"):
>>         #save original file name
>>         form_attachment.vars.filename=request.vars.attached_file.filename
>>     if form_attachment.process().accepted:
>>         response.flash = 'attachment saved'
>>     elif form_attachment.errors:
>>         response.flash = 'form has errors'
>>     # list existing attachments
>>     rows=db(db.attachment_module.id>0).select()
>>     response.view = 'attachment.html'
>>     return dict(form_attachment=form_attachment,
>>                 rows=rows)
>>
>> With this approach, I can still list the uploaded files and add 
>> additional ones (using the same view as before), but the download function 
>> no longer works.
>>
>> So my question is why not? Do I have to modify the standard download 
>> function, and how?
>> Hope these are not daft questions - any pointers would be appreciated.
>>
>> Andy
>>
>>
>>
>>
>>
>>
>>

-- 
Resources:
- http://web2py.com
- http://web2py.com/book (Documentation)
- http://github.com/web2py/web2py (Source code)
- https://code.google.com/p/web2py/issues/list (Report Issues)
--- 
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/d/optout.

Reply via email to