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.
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.