Skip to main content

Files and Folders Manipulation

Introduction

In the polyglot backend code of the Netuno platform, we can manipulate any file or folder.

Manipulation consists of being able to create, rename, and delete files and folders, change the contents of files, and list the contents of folders. In general, these are the operations we typically need to perform programmatically.

The Netuno platform has low-code programming features that allow you to manipulate the application's internal folders and files, but also any files and folders in the system in general, that is, outside the application.

This is useful when we need to automate a process that requires manipulating any file; let's see how.

The low-code polyglot programming features that allow you to manipulate files are:

Through these resources we have the methods to:

  • .file - Existing file.
  • .folder - Existing folder.
  • .path - A generic path can be either a file or a folder, and it may or may not exist.

With these methods we obtain an object of type File, which provides all the means for manipulating files, folders and paths in general, allowing operations such as:

  • Create files and folders.
  • Delete files and folders.
  • List the contents of folders.
  • Rename files and folders.
  • Read and write data to files.
  • Delete folders and their respective subfolders and files recursively.

Application

To perform the main file and folder manipulation operations within the application structure, we use the _app resource:

Folders in the Application

Ensures that an existing folder is retrieved, for example:

const myFolder = _app.folder("my/folder")

Files in the Application

Ensures that a file that exists is retrieved, for example:

const myFile = _app.file("my/folder/file.txt")

Paths in the Application

Retrieve a file or folder path, regardless of whether it exists or not, for example:

const newFile = _app.path("my/folder/new-file.txt")

Storage

To perform the main file and folder manipulation operations within the application's 📁 storage folder, we use the _storage resource:

Folders in Storage

Ensures that a folder that exists is retrieved, for example:

// The actual path to the folder will be:
// storage/filesystem/server/my/folder
const storageMyFolder = _storage.filesystem("server", "my/folder")
const myFolder = storageMyFolder.folder()

Files in Storage

Ensures that a file that exists is retrieved, for example:

// The actual file path will be:
// storage/filesystem/server/my/folder/file.txt
const storageFile = _storage.filesystem("server", "my/folder", "file.txt")
const file = storageArquivo.file()

Paths in Storage

Retrieve a file or folder path, regardless of whether it exists or not, for example:

// The actual new folder path will be:
// storage/filesystem/server/my/new-folder
const storageFolder = _storage.filesystem("server", "my/new-folder")
const folder = storageFolder.path()

// The actual new file path will be:
// storage/filesystem/server/my/folder/new-file.txt
const storageFile = _storage.filesystem("server", "my/folder", "new-file.txt")
const file = storageFile.path()

Operating System

To perform the main file and folder manipulation operations anywhere in the operating system, we use the _os feature:

Folders in the Operating System

Ensures that a folder that exists is retrieved, for example:

const myFolder = _os.folder("/tmp/my/folder")

Files in the Operating System

Ensures that a file that exists is retrieved, for example:

const myFile = _os.file("/tmp/my/folder/file.txt")

Paths in the Operating System

Retrieve a file or folder path, regardless of whether it exists or not, for example:

const newFile = _os.path("/tmp/my/folder/new-file.txt")

Create Folders

The mkdir method creates a folder.

In the following example, it creates the specific folder in the application root:

const folder = _app.path("temp")
folder.mkdir()

To create a subfolder within an existing folder, specify the full path, separating the folder hierarchy with /:

const subfolder = _app.path("temp/other")
subfolder.mkdir()

The mkdirs command creates the previous folders and/or subfolders if they don't exist, thus allowing you to create a folder structure in the application, for example:

const foldersPath = _app.path("temp/a/b/c")
foldersPath.mkdirs()

The _storage resource has the ensurePath method which checks if the path exists; if it doesn't, it will be created.

const file = _storage.filesystem(
"public",
"temp/subfolder",
"file.txt"
)
// Creates the folder structure if it doesn't already exist:
file.ensurePath()

Therefore, ensurePath guarantees that the folder structure exists.

Delete Files and Folders

With the delete method we can remove both folders and files, provided the folders are empty, see the example:

// Remove an empty folder:
const emptyFolder = _app.folder("folder/empty")
emptyFolder.delete()

// Remove a file:
const file = _app.file("folder/file.txt")
file.delete()

// Remove a path, empty folder, or file:
const path = _app.path("folder1/file-or-empty-folder")
path.delete()

Using deleteAll allows you to delete everything, that is, all files, folders, and subfolders recursively:

// Remove the folder and all its contents recursively:
const emptyFolder = _app.folder("folder/empty")
emptyFolder.deleteAll()

// Remove the path to a folder and all its contents,
// including subfolders and files:
const path = _app.path("path/folder")
path.deleteAll()

To delete only the files within the folder and not delete anything in the subfolders, we have deleteFiles, which allows you to specify an extension if you want to remove only files with a specific extension:

// Remove files only within the folder:
const folder = _app.folder("folder/example")
folder.deleteFiles()

// Remove files with the JPG extension only within the folder:
const path = _app.path("path/folder")
path.deleteFiles("jpg")

To delete only files recursively and maintain the folder structure, we have deleteAllFiles, which also allows you to specify an extension if you want to remove only a particular file type. See these two examples:

// Remove all files within the folder and subfolders:
const folder = _app.folder("folder/example")
folder.deleteAllFiles()

// Remove all files with the JPG extension within the folder and subfolders:
const path = _app.path("path/folder")
path.deleteAllFiles("jpg")

Rename or Move

To move a folder, it's the same as renaming it:

const folder = _app.folder("temp")
folder.renameTo("test")

To rename a folder and change its level in the folder hierarchy, it's the same as moving the folder:

const folder = _app.folder("temp/a/b")
folder.renameTo("test/z")

To move a subfolder without changing its name, simply specify the new path in the renameTo method:

const folder = _app.folder("test/other")
folder.renameTo("another")

Saving Content to Files

Generating content into files is done using the output method, which provides an object of type OutputStream.

To write the data to the output, we use the printAndClose method, which prints the content to the file and closes the file, saving the content.

Write Text File

Here's an example of how to create a file with text content:

_app.path("temp").mkdir()
const writer = _app.path("temp/file.txt").output()
writer.printAndClose("My text here...")

Whenever we use output, a new file is generated, so if you run the code again, the file will be recreated.

Write JSON file

Here's how we can save JSON data to files:

_app.path("temp").mkdir()
const writer = _app.path("temp/client.json").output()
writer.printAndClose(
_val.map()
.set("name", "Mary Joanna")
.set(
"register",
_val.list()
.add(1).add(2).add(3)
)
.toJSON()
)

To generate indented JSON, that is, formatted across multiple lines and tabbed, we can pass the number of spaces that will be tabbed, for example .toJSON(4).

More details about the toJSON in Values method.

Read Content in Files

Retrieving content from files is done through the input method, which provides an object of type InputStream.

To read the data from the input we use the method readAllAndClose, which processes the reading of the content in the file and closes the file.

Read Text File

Here's an example of how to read a file and retrieve its text content:

const file = _app.file("temp/file.txt")
const reader = file.input()
_log.info(reader.readAllAndClose())

Read JSON file

Here's how we can process JSON data obtained from files:

const file = _app.file("temp/file.txt")
const reader = file.input()
const data = _val.fromJSON(reader.readAllAndClose())
_log.info("File Data:", data)

More details about the fromJSON do recurso Val method of the Val resource.

Storage Specifics

The storage feature has several methods for direct use.

For example, we can access it through storage:

This means that we don't need to get the file or path to work with input or output.

Write Text File to Storage

When initializing storage for a file, we can perform writing using the output method, which obtains an instance of the OutputStream object that allows processing and reading the data.

So with OutputStream the method printAndClose, writes text (string) to the file and closes it.

See this example:

const txt = _storage.filesystem("server", "temp", "file.txt")
txt.ensurePath()
txt.output().printAndClose("My text here...")

Read Text File in Storage

When initializing storage for a file, we can read it using the input method, which obtains an instance of the InputStream object that allows processing and reading the data.

So with InputStream the method readAllAndClose, reads the entire file and closes it, returning the data as text (string).

See this example:

const txt = _storage.filesystem("server", "temp", "file.txt")
_log.info(txt.input().readAllAndClose())

Create a random file in Storage.

The _storage resource allows you to generate random filenames using the newRandomFile method.

You must initialize a storage instance for a folder path, and when executing the newRandomFile method, the desired file extension is passed.

The method returns a new instance of the storage for the automatically generated random file to be used in the initial folder.

See how to generate a file with the TXT extension with a random name:

const folder = _storage.filesystem("server", "temp")
const file = folder.newRandomFile("txt")
file.output().printAndClose("My text here...")

Conclusion

With Netuno's low-code polyglot framework, we can perform all the main folder and file operations directly.

By using the specific resources to manipulate files and folders in:

  • _app - Application
  • _storage - Application Storage
  • _os - Operating System

For best practices and organizational reasons, we should prioritize the use of storage; exceptions should be only for specific and strictly necessary cases.

Netuno automatically closes inputs and outputs at the end of service processing, but as a best practice, we should always try to close them.