Uhm, I was just thinking to return a string instead of the open stream. 
attached the patch (some refactoring bits added)

@Paolo: turns out that wiki has it's own "download()" function to handle 
files ..... in order to return cache headers you should do:

def yourwikiindex():
    zero = request.args(0) or 'index'
    if zero and zero.isdigit():
        response.headers['Cache-Control'] = 'max-age=315360000'
        response.headers['Expires'] = 'Thu, 31 Dec 2037 23:59:59 GMT'
    return auth.wiki()



On Monday, February 4, 2013 7:34:58 PM UTC+1, Massimo Di Pierro wrote:
>
> Honestly I would like to refactor all this logic in web2py. It was already 
> done for web3py:
>
> https://github.com/mdipierro/web3py/blob/master/web3py/stream.py
>
> Anyway, if you can help fix it in web2py, we can merge everything later
>
> Massimo
>
> On Monday, 4 February 2013 11:46:03 UTC-6, Paolo valleri wrote:
>>
>> I thought the same about postponing the opening of the file. Moreover, 
>> just after globals:344 in the stream(...) function I have added
>>
>>         if isinstance(stream, file):
>>             stream_file_or_304_or_206(stream.name,
>>                                       chunk_size=chunk_size,
>>                                       request=request,
>>                                       headers=headers,
>>                                       status=self.status)
>>
>> and finally I got a 304 :-). As a result we are on the right direction, 
>> although there is no reason to open the file and take only its name. We 
>> need definitely something better 
>>
>>  
>>
>>  Paolo
>>
>>
>> 2013/2/4 Niphlod <nip...@gmail.com>
>>
>>>
>>>
>>> On Monday, February 4, 2013 3:38:29 PM UTC+1, Paolo valleri wrote:
>>>>
>>>> Hi Niphlod, I am still trying to understand why the wiki uploads are 
>>>> not returned as 304. 
>>>> The function in charged to return either 200 or 304 is 
>>>> stream_file_or_304_or_206 in streamer.py. Moreover, this function is only 
>>>> called in globals.py inside stream(...). Please have a look at 
>>>> globals.py:344, In order to be called the parameter 'stream' must be a 
>>>> string but with 'common' downloads the stream is an open file. This is 
>>>> also 
>>>> documented by the comment in dal.py:9096. is what I've written correct ?
>>>>
>>>  
>>> seems so, but in this case I think it should be patched (as soon as I'll 
>>> get home). 
>>>
>>> For downloads that on the table are merely strings (i.e. on the table 
>>> there's the path to the actual file, usually in the "uploads" folder) the 
>>> correct way should be to "defer" the opening of the file down the line to 
>>> gluon.streamer. 
>>> A lot of logic has been added to store files on pyfilesystem (and 
>>> without much tests on that, I hope I won't brake anything) but I think that 
>>> for default "upload" file the logic needs to be revisited.
>>>
>>>  -- 
>>>  
>>> --- 
>>> 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 web2py+un...@googlegroups.com.
>>> For more options, visit https://groups.google.com/groups/opt_out.
>>>  
>>>  
>>>
>>
>>

-- 

--- 
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 web2py+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


diff -r f137cf18b70a gluon/dal.py
--- a/gluon/dal.py	lun feb 04 10:03:29 2013 -0600
+++ b/gluon/dal.py	lun feb 04 22:01:31 2013 +0100
@@ -876,7 +876,7 @@
                 # The reason is that we do not want to trigger
                 # a migration simply because a default value changes.
                 not_null = self.NOT_NULL(field.default, field_type)
-                ftype = ftype.replace('NOT NULL', not_null)            
+                ftype = ftype.replace('NOT NULL', not_null)
             sql_fields_aux[field_name] = dict(sql=ftype)
             # Postgres - PostGIS:
             # geometry fields are added after the table has been created, not now
@@ -1234,7 +1234,7 @@
                                  self.expand('%'+second, 'string'))
 
     def CONTAINS(self, first, second, case_sensitive=False):
-        if isinstance(second,Expression):            
+        if isinstance(second,Expression):
             field = self.expand(first)
             expr = self.expand(second,'string')
             if first.type.startswith('list:'):
@@ -3265,7 +3265,7 @@
 
     def execute(self,a):
         return self.log_execute(a.decode('utf8'))
-    
+
 
 class SybaseAdapter(MSSQLAdapter):
     drivers = ('Sybase',)
@@ -5037,7 +5037,7 @@
                 'list:reference': list,
         }
 
-    error_messages = {"javascript_needed": "This must yet be replaced" + 
+    error_messages = {"javascript_needed": "This must yet be replaced" +
                       " with javascript in order to work."}
 
     def __init__(self,db,uri='mongodb://127.0.0.1:5984/db',
@@ -5116,12 +5116,12 @@
                     raise ValueError(
                             "invalid objectid argument string: %s" % e)
             else:
-                raise ValueError("Invalid objectid argument string. " + 
+                raise ValueError("Invalid objectid argument string. " +
                                  "Requires an integer or base 16 value")
         elif isinstance(arg, self.ObjectId):
             return arg
         if not isinstance(arg, (int, long)):
-            raise TypeError("object_id argument must be of type " + 
+            raise TypeError("object_id argument must be of type " +
                             "ObjectId or an objectid representable integer")
         if arg == 0:
             hexvalue = "".zfill(24)
@@ -5153,7 +5153,7 @@
             return value
         return value
 
-    # Safe determines whether a asynchronious request is done or a 
+    # Safe determines whether a asynchronious request is done or a
     # synchronious action is done
     # For safety, we use by default synchronious requests
     def insert(self, table, fields, safe=None):
@@ -5273,7 +5273,7 @@
         elif len(fields) != 0:
             tablename = fields[0].tablename
         else:
-            raise SyntaxError("The table name could not be found in " + 
+            raise SyntaxError("The table name could not be found in " +
                               "the query nor from the select statement.")
 
         mongoqry_dict = self.expand(query)
@@ -5299,7 +5299,7 @@
                     sort=mongosort_list, snapshot=snapshot).count()}
         else:
             # pymongo cursor object
-            mongo_list_dicts = ctable.find(mongoqry_dict, 
+            mongo_list_dicts = ctable.find(mongoqry_dict,
                                 mongofields_dict, skip=limitby_skip,
                                 limit=limitby_limit, sort=mongosort_list,
                                 snapshot=snapshot)
@@ -5396,7 +5396,7 @@
         if safe is None:
             safe = self.safe
         amount = 0
-        amount = self.count(query, False)    
+        amount = self.count(query, False)
         if not isinstance(query, Query):
             raise RuntimeError("query type %s is not supported" % \
                                type(query))
@@ -5695,7 +5695,7 @@
     # This avoids the extra server names retrieval
 
     imapdb.define_tables({"inbox": "INBOX"})
-    
+
     # Selects without content/attachments/email columns will only
     # fetch header and flags
 
@@ -6088,7 +6088,7 @@
 
                     # keep the requests small for header/flags
                     if any([(field.name in ["content", "size",
-                                            "attachments", "email"]) for 
+                                            "attachments", "email"]) for
                            field in fields]):
                         imap_fields = "(RFC822 FLAGS)"
                     else:
@@ -7293,14 +7293,14 @@
             "/{person.name}/pets[pet.ownedby]/{pet.name}",
             "/{person.name}/pets[pet.ownedby]/{pet.name}/:field",
             ("/dogs[pet]", db.pet.info=='dog'),
-            ("/dogs[pet]/{pet.name.startswith}", db.pet.info=='dog'),       
+            ("/dogs[pet]/{pet.name.startswith}", db.pet.info=='dog'),
             ]
         parser = db.parse_as_rest(patterns,args,vars)
         if parser.status == 200:
             return dict(content=parser.response)
         else:
             raise HTTP(parser.status,parser.error)
-            
+
     def POST(table_name,**vars):
         if table_name == 'person':
             return db.person.validate_and_insert(**vars)
@@ -8797,7 +8797,7 @@
         return Expression(db, db._adapter.AS, self, alias, self.type)
 
     # GIS expressions
-    
+
     def st_asgeojson(self, precision=15, options=0, version=1):
         return Expression(self.db, self.db._adapter.ST_ASGEOJSON, self,
                           dict(precision=precision, options=options,
@@ -9131,7 +9131,7 @@
             stream = self.uploadfs.open(name, 'rb')
         else:
             # ## if file is on regular filesystem
-            stream = open(pjoin(file_properties['path'], name), 'rb')
+            stream = pjoin(file_properties['path'], name)
         return (filename, stream)
 
     def retrieve_file_properties(self, name, path=None):
diff -r f137cf18b70a gluon/globals.py
--- a/gluon/globals.py	lun feb 04 10:03:29 2013 -0600
+++ b/gluon/globals.py	lun feb 04 22:01:38 2013 +0100
@@ -308,8 +308,8 @@
         chunk_size=DEFAULT_CHUNK_SIZE,
         request=None,
         attachment=False,
-        filename=None,
-    ):
+        filename=None
+        ):
         """
         if a controller function::
 
@@ -403,8 +403,8 @@
             raise HTTP(404)
         headers = self.headers
         headers['Content-Type'] = contenttype(name)
-	if download_filename == None:
-	    download_filename = filename
+        if download_filename == None:
+            download_filename = filename
         if attachment:
             headers['Content-Disposition'] = \
                 'attachment; filename="%s"' % download_filename.replace('"','\"')
diff -r f137cf18b70a gluon/streamer.py
--- a/gluon/streamer.py	lun feb 04 10:03:29 2013 -0600
+++ b/gluon/streamer.py	lun feb 04 22:01:43 2013 +0100
@@ -46,8 +46,8 @@
     request=None,
     headers={},
     status=200,
-    error_message=None,
-):
+    error_message=None
+    ):
     if error_message is None:
         error_message = rewrite.THREAD_LOCAL.routes.error_message % 'invalid request'
     try:

Reply via email to