Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
W
wendelin
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Léo-Paul Géneau
wendelin
Commits
b1589abf
Commit
b1589abf
authored
Jul 15, 2015
by
Ivan Tyagov
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' into 'master'
DataArray: get array slice by HTTP Range Request See merge request !5
parents
049e87e5
c2481a75
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
147 additions
and
4 deletions
+147
-4
bt5/erp5_wendelin/DocumentTemplateItem/portal_components/document.erp5.DataArray.py
...TemplateItem/portal_components/document.erp5.DataArray.py
+142
-3
bt5/erp5_wendelin/DocumentTemplateItem/portal_components/document.erp5.DataArray.xml
...emplateItem/portal_components/document.erp5.DataArray.xml
+5
-1
No files found.
bt5/erp5_wendelin/DocumentTemplateItem/portal_components/document.erp5.DataArray.py
View file @
b1589abf
...
...
@@ -30,6 +30,11 @@ from AccessControl import ClassSecurityInfo
from
Products.ERP5Type
import
Permissions
,
PropertySheet
from
Products.ERP5.Document.BigFile
import
BigFile
from
wendelin.bigarray.array_zodb
import
ZBigArray
from
Products.ERP5.Document.File
import
_MARKER
from
ZPublisher
import
HTTPRangeSupport
from
webdav.common
import
rfc1123_date
from
DateTime
import
DateTime
from
mimetools
import
choose_boundary
import
transaction
class
DataArray
(
BigFile
):
...
...
@@ -69,16 +74,150 @@ class DataArray(BigFile):
Set numpy array to this ERP5 Data Array.
"""
self
.
array
=
value
# ZBigArray requirement: before we can compute it (with subobject
# .zfile) have to be made explicitly known to connection or current
# transaction committed (XXX: impossible to use as raises ConflictErrors)
transaction
.
commit
()
def
getArraySlice
(
self
,
start
,
end
):
"""
Implement array slicing in its most simple list alike form.
Any other advanced slicing techniques currently possible by getting
array reference directly.
"""
return
self
.
getArray
()[
start
:
end
]
\ No newline at end of file
return
self
.
getArray
()[
start
:
end
]
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'getSize'
)
def
getSize
(
self
,
default
=
None
):
"""
Implement getSize interface for ndarray
"""
return
self
.
getArray
().
nbytes
security
.
declareProtected
(
Permissions
.
View
,
'index_html'
)
def
index_html
(
self
,
REQUEST
,
RESPONSE
,
format
=
_MARKER
,
inline
=
_MARKER
,
**
kw
):
"""
Support streaming
"""
if
self
.
_range_request_handler
(
REQUEST
,
RESPONSE
):
# we served a chunk of content in response to a range request.
return
''
return
''
def
_range_request_handler
(
self
,
REQUEST
,
RESPONSE
):
RESPONSE
.
setHeader
(
"Content-Type"
,
"application/octet-stream"
)
# HTTP Range header handling: return True if we've served a range
# chunk out of our data.
range
=
REQUEST
.
get_header
(
'Range'
,
None
)
request_range
=
REQUEST
.
get_header
(
'Request-Range'
,
None
)
if
request_range
is
not
None
:
# Netscape 2 through 4 and MSIE 3 implement a draft version
# Later on, we need to serve a different mime-type as well.
range
=
request_range
if_range
=
REQUEST
.
get_header
(
'If-Range'
,
None
)
if
range
is
not
None
:
ranges
=
HTTPRangeSupport
.
parseRange
(
range
)
# get byte view of array because we interpret ranges in bytes
data
=
self
.
getArray
()[:].
view
(
"uint8"
).
ravel
()
if
if_range
is
not
None
:
# Only send ranges if the data isn't modified, otherwise send
# the whole object. Support both ETags and Last-Modified dates!
if
len
(
if_range
)
>
1
and
if_range
[:
2
]
==
'ts'
:
# ETag:
if
if_range
!=
self
.
http__etag
():
# Modified, so send a normal response. We delete
# the ranges, which causes us to skip to the 200
# response.
ranges
=
None
else
:
# Date
date
=
if_range
.
split
(
';'
)[
0
]
try
:
mod_since
=
long
(
DateTime
(
date
).
timeTime
())
except
:
mod_since
=
None
if
mod_since
is
not
None
:
last_mod
=
self
.
_data_mtime
()
if
last_mod
is
None
:
last_mod
=
0
last_mod
=
long
(
last_mod
)
if
last_mod
>
mod_since
:
# Modified, so send a normal response. We delete
# the ranges, which causes us to skip to the 200
# response.
ranges
=
None
if
ranges
:
# Search for satisfiable ranges.
satisfiable
=
0
for
start
,
end
in
ranges
:
if
start
<
self
.
getSize
():
satisfiable
=
1
break
if
not
satisfiable
:
RESPONSE
.
setHeader
(
'Content-Range'
,
'bytes */%d'
%
self
.
getSize
())
RESPONSE
.
setHeader
(
'Accept-Ranges'
,
'bytes'
)
RESPONSE
.
setHeader
(
'Last-Modified'
,
rfc1123_date
(
self
.
_data_mtime
()))
RESPONSE
.
setHeader
(
'Content-Type'
,
self
.
content_type
)
RESPONSE
.
setHeader
(
'Content-Length'
,
self
.
getSize
())
RESPONSE
.
setStatus
(
416
)
return
True
ranges
=
HTTPRangeSupport
.
expandRanges
(
ranges
,
self
.
getSize
())
if
len
(
ranges
)
==
1
:
# Easy case, set extra header and return partial set.
start
,
end
=
ranges
[
0
]
size
=
end
-
start
RESPONSE
.
setHeader
(
'Last-Modified'
,
rfc1123_date
(
self
.
_data_mtime
()))
RESPONSE
.
setHeader
(
'Content-Type'
,
self
.
content_type
)
RESPONSE
.
setHeader
(
'Content-Length'
,
size
)
RESPONSE
.
setHeader
(
'Accept-Ranges'
,
'bytes'
)
RESPONSE
.
setHeader
(
'Content-Range'
,
'bytes %d-%d/%d'
%
(
start
,
end
-
1
,
self
.
getSize
()))
RESPONSE
.
setStatus
(
206
)
# Partial content
RESPONSE
.
write
(
data
[
start
:
end
].
tobytes
())
else
:
boundary
=
choose_boundary
()
# Calculate the content length
size
=
(
8
+
len
(
boundary
)
+
# End marker length
len
(
ranges
)
*
(
# Constant lenght per set
49
+
len
(
boundary
)
+
len
(
self
.
content_type
)
+
len
(
'%d'
%
self
.
getSize
())))
for
start
,
end
in
ranges
:
# Variable length per set
size
=
(
size
+
len
(
'%d%d'
%
(
start
,
end
-
1
))
+
end
-
start
)
# Some clients implement an earlier draft of the spec, they
# will only accept x-byteranges.
draftprefix
=
(
request_range
is
not
None
)
and
'x-'
or
''
RESPONSE
.
setHeader
(
'Content-Length'
,
size
)
RESPONSE
.
setHeader
(
'Accept-Ranges'
,
'bytes'
)
RESPONSE
.
setHeader
(
'Last-Modified'
,
rfc1123_date
(
self
.
_data_mtime
()))
RESPONSE
.
setHeader
(
'Content-Type'
,
'multipart/%sbyteranges; boundary=%s'
%
(
draftprefix
,
boundary
))
RESPONSE
.
setStatus
(
206
)
# Partial content
for
start
,
end
in
ranges
:
RESPONSE
.
write
(
'
\
r
\
n
--%s
\
r
\
n
'
%
boundary
)
RESPONSE
.
write
(
'Content-Type: %s
\
r
\
n
'
%
self
.
content_type
)
RESPONSE
.
write
(
'Content-Range: bytes %d-%d/%d
\
r
\
n
\
r
\
n
'
%
(
start
,
end
-
1
,
self
.
getSize
()))
RESPONSE
.
write
(
data
[
start
:
end
].
tobytes
())
RESPONSE
.
write
(
'
\
r
\
n
--%s--
\
r
\
n
'
%
boundary
)
return
True
bt5/erp5_wendelin/DocumentTemplateItem/portal_components/document.erp5.DataArray.xml
View file @
b1589abf
...
...
@@ -45,7 +45,11 @@
<item>
<key>
<string>
text_content_warning_message
</string>
</key>
<value>
<tuple/>
<tuple>
<string>
W: 99, 42: Redefining built-in \'format\' (redefined-builtin)
</string>
<string>
W:113, 4: Redefining built-in \'range\' (redefined-builtin)
</string>
<string>
W:140, 10: No exception type(s) specified (bare-except)
</string>
</tuple>
</value>
</item>
<item>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment