Skip to main content

Managing files

When starting out coding with python, you could probably copy file paths from the File Explorer. However, when developing apps with VIKTOR, it's crucial to understand that these file paths don't function the same way as the apps are deployed on the cloud.

VIKTOR apps are stateless, meaning they reset with each session, files uploaded (via a FileField) to the cloud are only available for that session. Any files that are part of the app (such as an excel sheet integration) will reset for the next session. Additionally, VIKTOR applications follow a standardized structure, making them easy to move, store, and deploy on the cloud, a concept known as "containerized" development. However, any additions to the application are uploaded separately and are not part of the standardized package.

Therefore, it's essential to consider these factors when handling files on the VIKTOR platform. Understanding the file's intended actions are crucial for choosing the correct methods for file manipulation.

File paths

In most apps the code uses information from files on the hard drive. In order to access such files, a path must be provided. Python's built-in pathlib module can be used for this purpose.

caution

Never use a static path to access a file (e.g. '/home/users/foo/app/entity/file.txt', '../file.txt', or 'file.txt')! This might work fine when testing on your local machine, but will most likely crash when the app is published and runs on a server (different username, folder structure and operating system).

Assume an application with the following structure of the app directory:

app
├── entity_type_a
│ ├── __init__.py
│ ├── controller.py
│ └── parametrization.py
├── __init__.py
└── file.txt

We can make use of Path(__file__) as a starting point, which points to the file in which the code is invoked. On this path object, we can easily navigate to the parent directory by calling Path(__file__).parent. In the structure above, getting the file file.txt in the controller of entity_type_a can thus be done by:

# entity_type_a/controller.py
from pathlib import Path

entity_folder_path = Path(__file__).parent # entity_type_a
file_path = entity_folder_path.parent / 'file.txt'

with file_path.open() as f:
content = f.read()

This implementation allows your application/project/module to be portable. For example, the folder entity_type_a (and even controller.py!) can be renamed without breaking the link to file.txt, because the navigation is relative to the source file (controller.py).

Large files, storage and memory issues

For large files and calculations, it may be desirable to store some data in your application. VIKTOR offers a storage which can be used to store and retrieve files within an app workspace and the files will remain available. This can be very helpful in cases where (intermediate) results need to be shared between jobs. For more information on storage visit our storing results page. For processing large files, it is suggested to look into working with VIKTOR file objects in binary mode.

Production hosting and limits

When your application runs on production environments, a few things can be different than running it on development. Make sure you read up on files persistence between jobs and disk limits.