Allow WebAPI to specify filename and mime type for result data

PR #20377.
This commit is contained in:
Vladimir Golovnev 2024-02-12 09:07:09 +03:00 committed by GitHub
parent 8ef99b336c
commit 60bb819e2e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 43 additions and 19 deletions

View file

@ -1,6 +1,6 @@
/* /*
* Bittorrent Client using Qt and libtorrent. * Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2018, 2022 Vladimir Golovnev <glassez@yandex.ru> * Copyright (C) 2018-2024 Vladimir Golovnev <glassez@yandex.ru>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -37,12 +37,19 @@
#include "apierror.h" #include "apierror.h"
void APIResult::clear()
{
data.clear();
mimeType.clear();
filename.clear();
}
APIController::APIController(IApplication *app, QObject *parent) APIController::APIController(IApplication *app, QObject *parent)
: ApplicationComponent(app, parent) : ApplicationComponent(app, parent)
{ {
} }
QVariant APIController::run(const QString &action, const StringMap &params, const DataMap &data) APIResult APIController::run(const QString &action, const StringMap &params, const DataMap &data)
{ {
m_result.clear(); // clear result m_result.clear(); // clear result
m_params = params; m_params = params;
@ -79,20 +86,22 @@ void APIController::requireParams(const QVector<QString> &requiredParams) const
void APIController::setResult(const QString &result) void APIController::setResult(const QString &result)
{ {
m_result = result; m_result.data = result;
} }
void APIController::setResult(const QJsonArray &result) void APIController::setResult(const QJsonArray &result)
{ {
m_result = QJsonDocument(result); m_result.data = QJsonDocument(result);
} }
void APIController::setResult(const QJsonObject &result) void APIController::setResult(const QJsonObject &result)
{ {
m_result = QJsonDocument(result); m_result.data = QJsonDocument(result);
} }
void APIController::setResult(const QByteArray &result) void APIController::setResult(const QByteArray &result, const QString &mimeType, const QString &filename)
{ {
m_result = result; m_result.data = result;
m_result.mimeType = mimeType;
m_result.filename = filename;
} }

View file

@ -1,6 +1,6 @@
/* /*
* Bittorrent Client using Qt and libtorrent. * Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2018, 2022 Vladimir Golovnev <glassez@yandex.ru> * Copyright (C) 2018-2024 Vladimir Golovnev <glassez@yandex.ru>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -30,15 +30,23 @@
#include <QtContainerFwd> #include <QtContainerFwd>
#include <QObject> #include <QObject>
#include <QString>
#include <QVariant> #include <QVariant>
#include "base/applicationcomponent.h" #include "base/applicationcomponent.h"
class QString;
using DataMap = QHash<QString, QByteArray>; using DataMap = QHash<QString, QByteArray>;
using StringMap = QHash<QString, QString>; using StringMap = QHash<QString, QString>;
struct APIResult
{
QVariant data;
QString mimeType;
QString filename;
void clear();
};
class APIController : public ApplicationComponent<QObject> class APIController : public ApplicationComponent<QObject>
{ {
Q_OBJECT Q_OBJECT
@ -47,7 +55,7 @@ class APIController : public ApplicationComponent<QObject>
public: public:
explicit APIController(IApplication *app, QObject *parent = nullptr); explicit APIController(IApplication *app, QObject *parent = nullptr);
QVariant run(const QString &action, const StringMap &params, const DataMap &data = {}); APIResult run(const QString &action, const StringMap &params, const DataMap &data = {});
protected: protected:
const StringMap &params() const; const StringMap &params() const;
@ -57,10 +65,10 @@ protected:
void setResult(const QString &result); void setResult(const QString &result);
void setResult(const QJsonArray &result); void setResult(const QJsonArray &result);
void setResult(const QJsonObject &result); void setResult(const QJsonObject &result);
void setResult(const QByteArray &result); void setResult(const QByteArray &result, const QString &mimeType = {}, const QString &filename = {});
private: private:
StringMap m_params; StringMap m_params;
DataMap m_data; DataMap m_data;
QVariant m_result; APIResult m_result;
}; };

View file

@ -1442,5 +1442,5 @@ void TorrentsController::exportAction()
if (!result) if (!result)
throw APIError(APIErrorType::Conflict, tr("Unable to export torrent file. Error: %1").arg(result.error())); throw APIError(APIErrorType::Conflict, tr("Unable to export torrent file. Error: %1").arg(result.error()));
setResult(result.value()); setResult(result.value(), u"application/x-bittorrent"_s, (id.toString() + u".torrent"));
} }

View file

@ -352,18 +352,25 @@ void WebApplication::doProcessRequest()
try try
{ {
const QVariant result = controller->run(action, m_params, data); const APIResult result = controller->run(action, m_params, data);
switch (result.userType()) switch (result.data.userType())
{ {
case QMetaType::QJsonDocument: case QMetaType::QJsonDocument:
print(result.toJsonDocument().toJson(QJsonDocument::Compact), Http::CONTENT_TYPE_JSON); print(result.data.toJsonDocument().toJson(QJsonDocument::Compact), Http::CONTENT_TYPE_JSON);
break; break;
case QMetaType::QByteArray: case QMetaType::QByteArray:
print(result.toByteArray(), Http::CONTENT_TYPE_TXT); {
const auto resultData = result.data.toByteArray();
print(resultData, (!result.mimeType.isEmpty() ? result.mimeType : Http::CONTENT_TYPE_TXT));
if (!result.filename.isEmpty())
{
setHeader({u"Content-Disposition"_s, u"attachment; filename=\"%1\""_s.arg(result.filename)});
}
}
break; break;
case QMetaType::QString: case QMetaType::QString:
default: default:
print(result.toString(), Http::CONTENT_TYPE_TXT); print(result.data.toString(), Http::CONTENT_TYPE_TXT);
break; break;
} }
} }