Downloading files
A download action enables the user to download a file to hard disk upon clicking a button. In order to do so, the following steps need to be taken:
Add a
DownloadButton
in the parametrization class of the corresponding entity type:from viktor.parametrization import ViktorParametrization, DownloadButton
class Parametrization(ViktorParametrization):
download = DownloadButton('Download', method='download_file')Add the download method (in this case
download_file
) on the corresponding controller class of the entity type to link theDownloadButton
, and return the file (content) asDownloadResult
:from viktor import ViktorController
from viktor.result import DownloadResult
class Controller(ViktorController):
...
def download_file(self, params, **kwargs):
return DownloadResult('file content', 'filename.txt')
Downloading a File object
DownloadResult
directly accepts a File
object as input. This type is often returned by VIKTOR functions such as
utils' document conversions and external analyses. This allows for easy handling of result files:
from viktor import ViktorController
from viktor.result import DownloadResult
class Controller(ViktorController):
...
def download_spreadsheet(self, params, **kwargs):
...
filled_spreadsheet = render_spreadsheet(...)
return DownloadResult(filled_spreadsheet, 'filled_spreadsheet.xlsx')
def download_word_file(self, params, **kwargs):
...
word_file = render_word_file(...)
return DownloadResult(word_file, 'word_file.docx')
def download_scia_result(self, params, **kwargs):
...
result_file = scia_analysis.get_xml_output_file(as_file=True)
return DownloadResult(result_file, 'scia_result.xml')
Downloading other file types
It is also possible to download any other type of document (e.g. .txt
, .xml
, .json
, etc.). In these cases, the
DownloadResult
should be passed the file content as type str
or bytes
. Since VIKTOR does not offer specific
template for these file types, you will have to write the logic that generates the desired file content yourself.
Downloading multiple files
Downloading multiple files in one go is easy when using the zipped_files
argument in a DownloadResult
. The files
will be bundled in a zip-file with given file_name
:
DownloadResult(zipped_files={'my_file_1.txt': my_file_1, 'my_file_2.txt': my_file_2}, file_name="my_file.zip")
Alternatively, you can use the zipfile module from Python's standard library to create your own zip-file manually:
...
import zipfile
class Controller(ViktorController):
...
def download_zip(self, params, **kwargs):
...
file = File()
with zipfile.ZipFile(file.source, 'w', zipfile.ZIP_DEFLATED) as z:
z.writestr('my_file_1.txt', my_file_1_content)
z.writestr('my_file_2.txt', my_file_2_content)
return DownloadResult(file, file_name="my_file.zip")