-
Notifications
You must be signed in to change notification settings - Fork 51
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #80 from interactionresearchstudio/feature/downloa…
…d-all Download all / selected content with buttons
- Loading branch information
Showing
8 changed files
with
233 additions
and
38 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -248,4 +248,5 @@ dist | |
|
||
package-lock.json | ||
yarn-lock.json | ||
yarn.lock | ||
yarn.lock | ||
*.zip |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,7 +7,6 @@ | |
from subprocess import call | ||
import zipfile | ||
|
||
|
||
try: | ||
import picamera | ||
import picamera.array | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
from io import RawIOBase | ||
from zipfile import ZipFile, ZipInfo, ZIP_DEFLATED | ||
|
||
import os | ||
|
||
class ZipfileGenerator(): | ||
|
||
class UnseekableStream(RawIOBase): | ||
def __init__(self): | ||
self._buffer = b'' | ||
|
||
def writable(self): | ||
return True | ||
|
||
def write(self, b): | ||
if self.closed: | ||
raise ValueError('Stream was closed!') | ||
self._buffer += b | ||
return len(b) | ||
|
||
def get(self): | ||
chunk = self._buffer | ||
self._buffer = b'' | ||
return chunk | ||
|
||
# Constructor | ||
def __init__(self, | ||
paths = [], # { 'filename':'', 'arcname':'' } | ||
chunk_size = 0x8000): | ||
|
||
self.paths = paths | ||
self.chunk_size = chunk_size | ||
|
||
# Generator | ||
def get(self): | ||
|
||
output = ZipfileGenerator.UnseekableStream() | ||
|
||
with ZipFile(output, mode='w') as zf: | ||
|
||
for path in self.paths: | ||
|
||
try: | ||
if len(path['arcname']) == 0: | ||
path['arcname'] = path['filename'] | ||
|
||
z_info = ZipInfo.from_file(path['filename'], path['arcname']) | ||
|
||
# it's not worth the resources, achieves max 0.1% on JPEGs... | ||
#z_info.compress_type = ZIP_DEFLATED | ||
|
||
# should we try to fix the disk timestamps? | ||
# or should it be solved by setting the system time with the browser time? | ||
|
||
with open(path['filename'], 'rb') as entry, zf.open(z_info, mode='w') as dest: | ||
|
||
for chunk in iter(lambda: entry.read(self.chunk_size), b''): | ||
dest.write(chunk) | ||
# yield chunk of the zip file stream in bytes. | ||
yield output.get() | ||
|
||
except FileNotFoundError: | ||
# this should probably be logged, but how? | ||
pass | ||
|
||
# ZipFile was closed: get the final bytes | ||
yield output.get() | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
48 changes: 48 additions & 0 deletions
48
naturewatch_camera_server/static/client/src/gallery/ContentDownload.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import React from 'react'; | ||
import { Button, ButtonGroup } from 'react-bootstrap'; | ||
import PropTypes from 'prop-types'; | ||
|
||
class ContentDownload extends React.Component { | ||
renderButtons() { | ||
if (this.props.isSelectActive) { | ||
return this.renderDownloadButtons(); | ||
} | ||
else { | ||
return this.renderDownloadButton(); | ||
} | ||
} | ||
|
||
renderDownloadButton() { | ||
return( | ||
<Button variant="primary" onClick={() => {this.props.onSelectStart('download')}}>Download</Button> | ||
); | ||
} | ||
|
||
renderDownloadButtons() { | ||
return( | ||
<ButtonGroup aria-label="download"> | ||
<Button variant="primary" disabled={this.props.isDownloading} onClick={this.props.onDownloadAll}>Download All</Button> | ||
<Button variant="primary" disabled={this.props.isDownloading} onClick={this.props.onDownload}>Download Selected</Button> | ||
<Button variant="primary" onClick={this.props.onClearSelection}>Cancel</Button> | ||
</ButtonGroup> | ||
); | ||
} | ||
|
||
render() { | ||
return( | ||
<div className="content-select"> | ||
{this.renderButtons()} | ||
</div> | ||
); | ||
} | ||
} | ||
|
||
ContentDownload.propTypes = { | ||
isSelectActive: PropTypes.bool.isRequired, | ||
onSelectStart: PropTypes.func.isRequired, | ||
onDownload: PropTypes.func.isRequired, | ||
onDownloadAll: PropTypes.func.isRequired, | ||
onClearSelection: PropTypes.func.isRequired | ||
}; | ||
|
||
export default ContentDownload; |
Oops, something went wrong.