Skip to main content

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:

  1. 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')
  2. Add the download method (in this case download_file) on the corresponding controller class of the entity type to link the DownloadButton, and return the file (content) as DownloadResult:

    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")