[gen] Changes in the way binary files are downloaded.

This commit is contained in:
Gaetan Delannay 2015-01-29 16:36:43 +01:00
parent bd94641beb
commit 9d6aa23ae6
3 changed files with 29 additions and 12 deletions

View file

@ -248,9 +248,9 @@ class FileInfo:
self.modified = DateTime() self.modified = DateTime()
self.size = os.stat(fsName).st_size self.size = os.stat(fsName).st_size
def writeResponse(self, response, dbFolder='', disposition='inline'): def writeResponse(self, response, dbFolder='', disposition='attachment'):
'''Writes this file in the HTTP p_response object.''' '''Writes this file in the HTTP p_response object.'''
# As a preamble, initialise response headers. # As a preamble, initialise response headers
header = response.setHeader header = response.setHeader
header('Content-Disposition', header('Content-Disposition',
'%s;filename="%s"' % (disposition, self.uploadName)) '%s;filename="%s"' % (disposition, self.uploadName))

View file

@ -115,7 +115,8 @@ class Ref(Field):
<img src=":url('edit')" title=":_('object_edit')"/> <img src=":url('edit')" title=":_('object_edit')"/>
</a> </a>
<!-- Delete --> <!-- Delete -->
<img if="mayEdit and field.delete and tied.o.mayDelete()" <img var="mayDeleteViaField=inPickList and True or field.delete"
if="mayEdit and mayDeleteViaField and tied.o.mayDelete()"
class="clickable" title=":_('object_delete')" src=":url('delete')" class="clickable" title=":_('object_delete')" src=":url('delete')"
onclick=":'onDeleteObject(%s)' % q(tiedUid)"/> onclick=":'onDeleteObject(%s)' % q(tiedUid)"/>
<!-- Unlink --> <!-- Unlink -->
@ -289,7 +290,10 @@ class Ref(Field):
<!-- The "title" field --> <!-- The "title" field -->
<x if="refField.name == 'title'"> <x if="refField.name == 'title'">
<x if="mayView"> <x if="mayView">
<x>:field.pxObjectTitle</x> <x if="not field.menuUrlMethod">:field.pxObjectTitle</x>
<a if="field.menuUrlMethod"
var2="info=field.getMenuUrl(zobj, tied)"
href=":info[0]" target=":info[1]">:tied.title</a>
<x if="tied.o.mayAct()">:field.pxObjectActions</x> <x if="tied.o.mayAct()">:field.pxObjectActions</x>
</x> </x>
<div if="not mayView"> <div if="not mayView">
@ -372,7 +376,8 @@ class Ref(Field):
object in the menu. --> object in the menu. -->
<x if="singleObject" var2="tied=menu.objects[0]"> <x if="singleObject" var2="tied=menu.objects[0]">
<a if="field.menuUrlMethod" class="dropdownMenu" <a if="field.menuUrlMethod" class="dropdownMenu"
href=":field.getMenuUrl(zobj, tied)" var2="info=field.getMenuUrl(zobj, tied)"
href=":info[0]" target=":info[1]"
title=":tied.o.getShownValue('title')">:field.pxMenu</a> title=":tied.o.getShownValue('title')">:field.pxMenu</a>
<a if="not field.menuUrlMethod" class="dropdownMenu" <a if="not field.menuUrlMethod" class="dropdownMenu"
var2="linkInPopup=inPopup or (target.target != '_self')" var2="linkInPopup=inPopup or (target.target != '_self')"
@ -392,7 +397,8 @@ class Ref(Field):
<!-- A specific link may have to be computed from <!-- A specific link may have to be computed from
field.menuUrlMethod --> field.menuUrlMethod -->
<a if="field.menuUrlMethod" <a if="field.menuUrlMethod"
href=":field.getMenuUrl(zobj, tied)">:tied.title</a> var2="info=field.getMenuUrl(zobj, tied)"
href=":info[0]" target=":info[1]">:tied.title</a>
<!-- Show standard pxObjectTitle else --> <!-- Show standard pxObjectTitle else -->
<x if="not field.menuUrlMethod">:field.pxObjectTitle</x> <x if="not field.menuUrlMethod">:field.pxObjectTitle</x>
<x if="tied.o.mayAct()">:field.pxObjectActions</x> <x if="tied.o.mayAct()">:field.pxObjectActions</x>
@ -717,7 +723,11 @@ class Ref(Field):
# the menu as an icon instead of a text. # the menu as an icon instead of a text.
self.menuInfoMethod = menuInfoMethod self.menuInfoMethod = menuInfoMethod
# "menuUrlMethod" is an optional method that allows to compute an # "menuUrlMethod" is an optional method that allows to compute an
# alternative URL for the tied object that is shown within the menu. # alternative URL for the tied object that is shown within the menu
# (when render is "menus"). It can also be used with render being "list"
# as well. The method can return a URL as a string, or, alternately, a
# tuple (url, target), "target" being a string that will be used for
# the "target" attribute of the corresponding XHTML "a" tag.
self.menuUrlMethod = menuUrlMethod self.menuUrlMethod = menuUrlMethod
# "showActions" determines if we must show or not actions on every tied # "showActions" determines if we must show or not actions on every tied
# object. Values can be: True, False or "inline". If True, actions will # object. Values can be: True, False or "inline". If True, actions will
@ -966,8 +976,10 @@ class Ref(Field):
render mode, tied object's order is lost and navigation is render mode, tied object's order is lost and navigation is
impossible.''' impossible.'''
if self.menuUrlMethod: if self.menuUrlMethod:
return self.menuUrlMethod(zobj.appy(), tied) res = self.menuUrlMethod(zobj.appy(), tied)
return tied.o.getUrl(nav='') if isinstance(res, str): return res, '_self'
return res
return tied.o.getUrl(nav=''), '_self'
def getStartNumber(self, render, req, ajaxHookId): def getStartNumber(self, render, req, ajaxHookId):
'''This method returns the index of the first linked object that must be '''This method returns the index of the first linked object that must be

View file

@ -1696,7 +1696,8 @@ class BaseMixin:
name is in the request. This name can also represent an attribute name is in the request. This name can also represent an attribute
storing an image within a rich text field. If p_name is not given, it storing an image within a rich text field. If p_name is not given, it
is retrieved from the request.''' is retrieved from the request.'''
name = self.REQUEST.get('name') rq = self.REQUEST
name = rq.get('name')
if not name: return if not name: return
# Security check # Security check
if '_img_' not in name: if '_img_' not in name:
@ -1704,10 +1705,14 @@ class BaseMixin:
else: else:
field = self.getAppyType(name.split('_img_')[0]) field = self.getAppyType(name.split('_img_')[0])
self.mayView(field.readPermission, raiseError=True) self.mayView(field.readPermission, raiseError=True)
# Write the file in the HTTP response
info = getattr(self.aq_base, name, None) info = getattr(self.aq_base, name, None)
if info: if info:
# Write the file in the HTTP response. # Content disposition may be given in the request
info.writeResponse(self.REQUEST.RESPONSE, self.getDbFolder()) disposition = rq.get('disposition', 'attachment')
if disposition not in ('inline', 'attachment'):
disposition = 'attachment'
info.writeResponse(rq.RESPONSE, self.getDbFolder(), disposition)
def upload(self): def upload(self):
'''Receives an image uploaded by the user via ckeditor and stores it in '''Receives an image uploaded by the user via ckeditor and stores it in