WebAPI: Add metadata in /app/getDirectoryContent response

## Description

Send file/folder metadata instead of just the name of a filesystem entry.
Currently the endpoint only sends a list of string, containing the path of each entry, without specifying its type (file or folder).
The optional `withMetadata` flag has been added to provide metadata and to prevent breaking changes with older versions.
If `true`, JSON response will be an array of objects instead of an array of strings.

This object contains:
- `name`: the name of the file system entry (without path)
- `type`: Whether the file system entry is a "file" or a "dir"
- `creation_date`: file system entry's creation date
- `last_access_date`: file system entry's last access date
- `last_modification_date`: file system entry's last modification date

If the entry is a file, a `size` field is present with the file size in bytes.

## Objective

Build a server file browser inside WebUIs, feature is currently being developed for VueTorrent.
It will include file metadata, filtering and sorting on the different fields.

PR #22813.
This commit is contained in:
Rémi Marseault
2025-06-07 17:02:48 +02:00
committed by GitHub
parent 05bcc4e175
commit 8e2125ee72
3 changed files with 61 additions and 4 deletions

View File

@@ -77,6 +77,12 @@ const QString KEY_COOKIE_DOMAIN = u"domain"_s;
const QString KEY_COOKIE_PATH = u"path"_s;
const QString KEY_COOKIE_VALUE = u"value"_s;
const QString KEY_COOKIE_EXPIRATION_DATE = u"expirationDate"_s;
const QString KEY_FILE_METADATA_NAME = u"name"_s;
const QString KEY_FILE_METADATA_TYPE = u"type"_s;
const QString KEY_FILE_METADATA_SIZE = u"size"_s;
const QString KEY_FILE_METADATA_CREATION_DATE = u"creation_date"_s;
const QString KEY_FILE_METADATA_LAST_ACCESS_DATE = u"last_access_date"_s;
const QString KEY_FILE_METADATA_LAST_MODIFICATION_DATE = u"last_modification_date"_s;
void AppController::webapiVersionAction()
{
@@ -1210,10 +1216,40 @@ void AppController::getDirectoryContentAction()
throw APIError(APIErrorType::BadParams, tr("Invalid mode, allowed values: %1").arg(u"all, dirs, files"_s));
};
const bool withMetadata {Utils::String::parseBool(params()[u"withMetadata"_s]).value_or(false)};
QJsonArray ret;
QDirIterator it {dirPath, (QDir::NoDotAndDotDot | parseDirectoryContentMode(visibility))};
while (it.hasNext())
ret.append(it.next());
{
if (withMetadata)
{
const QFileInfo fileInfo = it.nextFileInfo();
QJsonObject fileObject
{
{KEY_FILE_METADATA_NAME, fileInfo.fileName()},
{KEY_FILE_METADATA_CREATION_DATE, Utils::DateTime::toSecsSinceEpoch(fileInfo.birthTime())},
{KEY_FILE_METADATA_LAST_ACCESS_DATE, Utils::DateTime::toSecsSinceEpoch(fileInfo.lastRead())},
{KEY_FILE_METADATA_LAST_MODIFICATION_DATE, Utils::DateTime::toSecsSinceEpoch(fileInfo.lastModified())},
};
if (fileInfo.isDir())
{
fileObject.insert(KEY_FILE_METADATA_TYPE, u"dir"_s);
}
else if (fileInfo.isFile())
{
fileObject.insert(KEY_FILE_METADATA_TYPE, u"file"_s);
fileObject.insert(KEY_FILE_METADATA_SIZE, fileInfo.size());
}
ret.append(fileObject);
}
else
{
ret.append(it.next());
}
}
setResult(ret);
}