mirror of
https://github.com/oatpp/oatpp.git
synced 2025-04-18 19:00:23 +08:00
multipart: use data::resource::Resource.
This commit is contained in:
parent
8d342e2967
commit
9a44c1f463
@ -216,8 +216,8 @@ add_library(oatpp
|
||||
oatpp/web/client/RequestExecutor.hpp
|
||||
oatpp/web/client/RetryPolicy.cpp
|
||||
oatpp/web/client/RetryPolicy.hpp
|
||||
oatpp/web/mime/multipart/FileStreamProvider.cpp
|
||||
oatpp/web/mime/multipart/FileStreamProvider.hpp
|
||||
oatpp/web/mime/multipart/FileResourceProvider.cpp
|
||||
oatpp/web/mime/multipart/FileResourceProvider.hpp
|
||||
oatpp/web/mime/multipart/InMemoryPartReader.cpp
|
||||
oatpp/web/mime/multipart/InMemoryPartReader.hpp
|
||||
oatpp/web/mime/multipart/Multipart.cpp
|
||||
|
@ -22,45 +22,30 @@
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#include "FileStreamProvider.hpp"
|
||||
#include "FileResourceProvider.hpp"
|
||||
|
||||
#include "oatpp/core/data/stream/FileStream.hpp"
|
||||
#include "oatpp/core/data/resource/File.hpp"
|
||||
|
||||
namespace oatpp { namespace web { namespace mime { namespace multipart {
|
||||
|
||||
FileStreamProvider::FileStreamProvider(const oatpp::String& filename)
|
||||
FileResourceProvider::FileResourceProvider(const oatpp::String& filename)
|
||||
: m_filename(filename)
|
||||
{}
|
||||
|
||||
std::shared_ptr<FileStreamProvider::OutputStream> FileStreamProvider::getOutputStream(const std::shared_ptr<Part>& part) {
|
||||
std::shared_ptr<data::resource::Resource> FileResourceProvider::getResource(const std::shared_ptr<Part>& part) {
|
||||
(void)part;
|
||||
return std::make_shared<data::stream::FileOutputStream>(m_filename->c_str());
|
||||
return std::make_shared<data::resource::File>(m_filename->c_str());
|
||||
}
|
||||
|
||||
std::shared_ptr<FileStreamProvider::InputStream> FileStreamProvider::getInputStream(const std::shared_ptr<Part>& part) {
|
||||
(void)part;
|
||||
return std::make_shared<data::stream::FileInputStream>(m_filename->c_str());
|
||||
}
|
||||
|
||||
|
||||
AsyncFileStreamProvider::AsyncFileStreamProvider(const oatpp::String& filename)
|
||||
AsyncFileResourceProvider::AsyncFileResourceProvider(const oatpp::String& filename)
|
||||
: m_filename(filename)
|
||||
{}
|
||||
|
||||
async::CoroutineStarter AsyncFileStreamProvider::getOutputStreamAsync(const std::shared_ptr<Part>& part,
|
||||
std::shared_ptr<data::stream::OutputStream>& stream)
|
||||
async::CoroutineStarter AsyncFileResourceProvider::getResourceAsync(const std::shared_ptr<Part>& part,
|
||||
std::shared_ptr<data::resource::Resource>& stream)
|
||||
{
|
||||
(void)part;
|
||||
stream = std::make_shared<data::stream::FileOutputStream>(m_filename->c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
async::CoroutineStarter AsyncFileStreamProvider::getInputStreamAsync(const std::shared_ptr<Part>& part,
|
||||
std::shared_ptr<data::stream::InputStream>& stream)
|
||||
{
|
||||
(void)part;
|
||||
stream = std::make_shared<data::stream::FileInputStream>(m_filename->c_str());
|
||||
stream = std::make_shared<data::resource::File>(m_filename->c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -68,13 +53,13 @@ async::CoroutineStarter AsyncFileStreamProvider::getInputStreamAsync(const std::
|
||||
// Other functions
|
||||
|
||||
std::shared_ptr<PartReader> createFilePartReader(const oatpp::String& filename, v_io_size maxDataSize) {
|
||||
auto provider = std::make_shared<FileStreamProvider>(filename);
|
||||
auto provider = std::make_shared<FileResourceProvider>(filename);
|
||||
auto reader = std::make_shared<StreamPartReader>(provider, maxDataSize);
|
||||
return reader;
|
||||
}
|
||||
|
||||
std::shared_ptr<AsyncPartReader> createAsyncFilePartReader(const oatpp::String& filename, v_io_size maxDataSize) {
|
||||
auto provider = std::make_shared<AsyncFileStreamProvider>(filename);
|
||||
auto provider = std::make_shared<AsyncFileResourceProvider>(filename);
|
||||
auto reader = std::make_shared<AsyncStreamPartReader>(provider, maxDataSize);
|
||||
return reader;
|
||||
}
|
@ -33,17 +33,7 @@ namespace oatpp { namespace web { namespace mime { namespace multipart {
|
||||
/**
|
||||
* Stream provider for `StreamPartReader`.
|
||||
*/
|
||||
class FileStreamProvider : public PartReaderStreamProvider {
|
||||
public:
|
||||
/**
|
||||
* Convenience typedef for &id:oatpp::data::stream::OutputStream;.
|
||||
*/
|
||||
typedef oatpp::data::stream::OutputStream OutputStream;
|
||||
|
||||
/**
|
||||
* Convenience typedef for &id:oatpp::data::stream::InputStream;.
|
||||
*/
|
||||
typedef oatpp::data::stream::InputStream InputStream;
|
||||
class FileResourceProvider : public PartReaderResourceProvider {
|
||||
private:
|
||||
oatpp::String m_filename;
|
||||
public:
|
||||
@ -52,41 +42,21 @@ public:
|
||||
* Constructor.
|
||||
* @param filename
|
||||
*/
|
||||
FileStreamProvider(const oatpp::String& filename);
|
||||
FileResourceProvider(const oatpp::String& filename);
|
||||
|
||||
/**
|
||||
* Get stream to write (save) part data in.
|
||||
* Get resource to write (save) part data in.
|
||||
* @param part
|
||||
* @return
|
||||
*/
|
||||
std::shared_ptr<OutputStream> getOutputStream(const std::shared_ptr<Part>& part) override;
|
||||
|
||||
/**
|
||||
* Get stream to read part data from. <br>
|
||||
* This method is called after all data has been streamed to OutputStream.
|
||||
* @param part
|
||||
* @return
|
||||
*/
|
||||
std::shared_ptr<InputStream> getInputStream(const std::shared_ptr<Part>& part) override;
|
||||
std::shared_ptr<data::resource::Resource> getResource(const std::shared_ptr<Part>& part) override;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Async stream provider for `AsyncStreamPartReader`.
|
||||
*/
|
||||
class AsyncFileStreamProvider : public AsyncPartReaderStreamProvider {
|
||||
public:
|
||||
/**
|
||||
* Convenience typedef for &id:oatpp::data::stream::OutputStream;.
|
||||
*/
|
||||
typedef oatpp::data::stream::OutputStream OutputStream;
|
||||
|
||||
/**
|
||||
* Convenience typedef for &id:oatpp::data::stream::InputStream;.
|
||||
*/
|
||||
typedef oatpp::data::stream::InputStream InputStream;
|
||||
public:
|
||||
|
||||
class AsyncFileResourceProvider : public AsyncPartReaderResourceProvider {
|
||||
private:
|
||||
oatpp::String m_filename;
|
||||
public:
|
||||
@ -95,26 +65,16 @@ public:
|
||||
* Constructor.
|
||||
* @param filename
|
||||
*/
|
||||
AsyncFileStreamProvider(const oatpp::String& filename);
|
||||
AsyncFileResourceProvider(const oatpp::String& filename);
|
||||
|
||||
/**
|
||||
* Get stream to write (save) part data to.
|
||||
* @param part
|
||||
* @param stream - put here pointer to obtained stream.
|
||||
* @param resource - put here pointer to obtained resource.
|
||||
* @return
|
||||
*/
|
||||
async::CoroutineStarter getOutputStreamAsync(const std::shared_ptr<Part>& part,
|
||||
std::shared_ptr<data::stream::OutputStream>& stream) override;
|
||||
|
||||
/**
|
||||
* Get stream to read part data from. <br>
|
||||
* This method is called after all data has been streamed to OutputStream.
|
||||
* @param part
|
||||
* @param stream - put here pointer to obtained stream.
|
||||
* @return
|
||||
*/
|
||||
async::CoroutineStarter getInputStreamAsync(const std::shared_ptr<Part>& part,
|
||||
std::shared_ptr<data::stream::InputStream>& stream) override;
|
||||
async::CoroutineStarter getResourceAsync(const std::shared_ptr<Part>& part,
|
||||
std::shared_ptr<data::resource::Resource>& resource) override;
|
||||
|
||||
};
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
#include "InMemoryPartReader.hpp"
|
||||
|
||||
#include "oatpp/core/data/resource/InMemoryData.hpp"
|
||||
#include "oatpp/core/data/stream/BufferStream.hpp"
|
||||
|
||||
namespace oatpp { namespace web { namespace mime { namespace multipart {
|
||||
@ -75,8 +76,7 @@ void InMemoryPartReader::onPartData(const std::shared_ptr<Part>& part, const cha
|
||||
auto fullData = buffer->toString();
|
||||
buffer->clear();
|
||||
part->clearTag();
|
||||
auto stream = std::make_shared<data::stream::BufferInputStream>(fullData.getPtr(), fullData->data(), fullData->size());
|
||||
part->setDataInfo(stream, fullData, fullData->size());
|
||||
part->setPayload(std::make_shared<data::resource::InMemoryData>(fullData));
|
||||
}
|
||||
|
||||
}
|
||||
@ -130,8 +130,7 @@ async::CoroutineStarter AsyncInMemoryPartReader::onPartDataAsync(const std::shar
|
||||
auto fullData = buffer->toString();
|
||||
buffer->clear();
|
||||
part->clearTag();
|
||||
auto stream = std::make_shared<data::stream::BufferInputStream>(fullData.getPtr(), fullData->data(), fullData->size());
|
||||
part->setDataInfo(stream, fullData, fullData->size());
|
||||
part->setPayload(std::make_shared<data::resource::InMemoryData>(fullData));
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -31,14 +31,9 @@
|
||||
|
||||
namespace oatpp { namespace web { namespace mime { namespace multipart {
|
||||
|
||||
Part::Part(const Headers &headers,
|
||||
const std::shared_ptr<data::stream::InputStream> &inputStream,
|
||||
const oatpp::String& inMemoryData,
|
||||
v_int64 knownSize)
|
||||
Part::Part(const Headers &headers, const std::shared_ptr<data::resource::Resource>& payload)
|
||||
: m_headers(headers)
|
||||
, m_inputStream(inputStream)
|
||||
, m_inMemoryData(inMemoryData)
|
||||
, m_knownSize(knownSize)
|
||||
, m_payload(payload)
|
||||
{
|
||||
|
||||
auto contentDisposition = m_headers.getAsMemoryLabel<oatpp::data::share::StringKeyLabel>("Content-Disposition");
|
||||
@ -54,24 +49,12 @@ Part::Part(const Headers &headers,
|
||||
|
||||
}
|
||||
|
||||
|
||||
Part::Part(const Headers& headers) : Part(headers, nullptr, nullptr, -1) {}
|
||||
|
||||
Part::Part() : Part(Headers(), nullptr, nullptr, -1) {}
|
||||
|
||||
void Part::setDataInfo(const std::shared_ptr<data::stream::InputStream>& inputStream,
|
||||
const oatpp::String& inMemoryData,
|
||||
v_int64 knownSize)
|
||||
{
|
||||
m_inputStream = inputStream;
|
||||
m_inMemoryData = inMemoryData;
|
||||
m_knownSize = knownSize;
|
||||
void Part::setPayload(const std::shared_ptr<data::resource::Resource>& payload) {
|
||||
m_payload = payload;
|
||||
}
|
||||
|
||||
void Part::setDataInfo(const std::shared_ptr<data::stream::InputStream>& inputStream) {
|
||||
m_inputStream = inputStream;
|
||||
m_inMemoryData = nullptr;
|
||||
m_knownSize = -1;
|
||||
std::shared_ptr<data::resource::Resource> Part::getPayload() {
|
||||
return m_payload;
|
||||
}
|
||||
|
||||
oatpp::String Part::getName() const {
|
||||
@ -100,18 +83,6 @@ bool Part::putHeaderIfNotExists(const oatpp::data::share::StringKeyLabelCI& key,
|
||||
return m_headers.putIfNotExists(key, value);
|
||||
}
|
||||
|
||||
std::shared_ptr<data::stream::InputStream> Part::getInputStream() const {
|
||||
return m_inputStream;
|
||||
}
|
||||
|
||||
oatpp::String Part::getInMemoryData() const {
|
||||
return m_inMemoryData;
|
||||
}
|
||||
|
||||
v_int64 Part::getKnownSize() const {
|
||||
return m_knownSize;
|
||||
}
|
||||
|
||||
void Part::setTag(const char* tagName, const std::shared_ptr<oatpp::base::Countable>& tagObject) {
|
||||
m_tagName = tagName;
|
||||
m_tagObject = tagObject;
|
||||
|
@ -26,7 +26,7 @@
|
||||
#define oatpp_web_mime_multipart_Part_hpp
|
||||
|
||||
#include "oatpp/core/data/share/LazyStringMap.hpp"
|
||||
#include "oatpp/core/data/stream/Stream.hpp"
|
||||
#include "oatpp/core/data/resource/Resource.hpp"
|
||||
|
||||
namespace oatpp { namespace web { namespace mime { namespace multipart {
|
||||
|
||||
@ -44,52 +44,35 @@ private:
|
||||
oatpp::String m_name;
|
||||
oatpp::String m_filename;
|
||||
Headers m_headers;
|
||||
std::shared_ptr<data::stream::InputStream> m_inputStream;
|
||||
oatpp::String m_inMemoryData;
|
||||
v_int64 m_knownSize;
|
||||
std::shared_ptr<data::resource::Resource> m_payload;
|
||||
private:
|
||||
const char* m_tagName;
|
||||
std::shared_ptr<oatpp::base::Countable> m_tagObject;
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param headers - headers of the part.
|
||||
* @param inputStream - input stream of the part data.
|
||||
* @param inMemoryData - possible in-memory data of the part. Same data as the referred by input stream. For convenience purposes.
|
||||
* @param knownSize - known size of the data in the input stream. Pass `-1` value if size is unknown.
|
||||
*/
|
||||
Part(const Headers& headers,
|
||||
const std::shared_ptr<data::stream::InputStream>& inputStream,
|
||||
const oatpp::String& inMemoryData,
|
||||
v_int64 knownSize);
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param headers - headers of the part.
|
||||
*/
|
||||
Part(const Headers& headers);
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
Part();
|
||||
Part() = default;
|
||||
|
||||
/**
|
||||
* Set part data info.
|
||||
* @param inputStream - input stream of the part data.
|
||||
* @param inMemoryData - possible in-memory data of the part. Same data as the referred by input stream. For convenience purposes.
|
||||
* @param knownSize - known size of the data in the input stream. Pass `-1` value if size is unknown.
|
||||
* Constructor.
|
||||
* @param headers - headers of the part.
|
||||
* @param payload - part payload.
|
||||
*/
|
||||
void setDataInfo(const std::shared_ptr<data::stream::InputStream>& inputStream,
|
||||
const oatpp::String& inMemoryData,
|
||||
v_int64 knownSize);
|
||||
Part(const Headers& headers, const std::shared_ptr<data::resource::Resource>& payload = nullptr);
|
||||
|
||||
/**
|
||||
* Same as `setDataInfo(inputStream, nullptr, -1);.`
|
||||
* @param inputStream - input stream of the part data.
|
||||
* Set payload.
|
||||
* @param payload
|
||||
*/
|
||||
void setDataInfo(const std::shared_ptr<data::stream::InputStream>& inputStream);
|
||||
void setPayload(const std::shared_ptr<data::resource::Resource>& payload);
|
||||
|
||||
/**
|
||||
* Get payload.
|
||||
* @return
|
||||
*/
|
||||
std::shared_ptr<data::resource::Resource> getPayload();
|
||||
|
||||
/**
|
||||
* Get name of the part.
|
||||
@ -131,26 +114,6 @@ public:
|
||||
*/
|
||||
bool putHeaderIfNotExists(const oatpp::data::share::StringKeyLabelCI& key, const oatpp::data::share::StringKeyLabel& value);
|
||||
|
||||
/**
|
||||
* Get input stream of the part data.
|
||||
* @return - input stream of the part data.
|
||||
*/
|
||||
std::shared_ptr<data::stream::InputStream> getInputStream() const;
|
||||
|
||||
/**
|
||||
* Get in-memory data (if applicable). <br>
|
||||
* It may be possible set for the part in case of storing part data in memory. <br>
|
||||
* This property is optional. Preferred way to access data of the part is through `getInputStream()` method.
|
||||
* @return - in-memory data.
|
||||
*/
|
||||
oatpp::String getInMemoryData() const;
|
||||
|
||||
/**
|
||||
* Return known size of the part data.
|
||||
* @return - known size of the part data. `-1` - if size is unknown.
|
||||
*/
|
||||
v_int64 getKnownSize() const;
|
||||
|
||||
/**
|
||||
* Tag-object - object used to associate some data with the Part. <br>
|
||||
* Ex.: used by &id:oatpp::web::mime::multipart::InMemoryPartReader;. to
|
||||
|
@ -28,15 +28,15 @@ namespace oatpp { namespace web { namespace mime { namespace multipart {
|
||||
|
||||
const char* const StreamPartReader::TAG_NAME = "[oatpp::web::mime::multipart::StreamPartReader::TAG]";
|
||||
|
||||
StreamPartReader::StreamPartReader(const std::shared_ptr<PartReaderStreamProvider>& streamProvider,
|
||||
StreamPartReader::StreamPartReader(const std::shared_ptr<PartReaderResourceProvider>& resourceProvider,
|
||||
v_io_size maxDataSize)
|
||||
: m_streamProvider(streamProvider)
|
||||
: m_resourceProvider(resourceProvider)
|
||||
, m_maxDataSize(maxDataSize)
|
||||
{}
|
||||
|
||||
void StreamPartReader::onNewPart(const std::shared_ptr<Part>& part) {
|
||||
|
||||
if(!m_streamProvider) {
|
||||
if(!m_resourceProvider) {
|
||||
throw std::runtime_error("[oatpp::web::mime::multipart::StreamPartReader::onNewPart()]: Error. Stream provider is nullptr.");
|
||||
}
|
||||
|
||||
@ -48,7 +48,8 @@ void StreamPartReader::onNewPart(const std::shared_ptr<Part>& part) {
|
||||
}
|
||||
|
||||
auto tagObject = std::make_shared<TagObject>();
|
||||
tagObject->outputStream = m_streamProvider->getOutputStream(part);
|
||||
tagObject->resource = m_resourceProvider->getResource(part);
|
||||
tagObject->outputStream = tagObject->resource->openOutputStream();
|
||||
part->setTag(TAG_NAME, tagObject);
|
||||
|
||||
}
|
||||
@ -82,8 +83,8 @@ void StreamPartReader::onPartData(const std::shared_ptr<Part>& part, const char*
|
||||
}
|
||||
tagObject->size += res;
|
||||
} else {
|
||||
part->setPayload(tagObject->resource);
|
||||
part->clearTag();
|
||||
part->setDataInfo(m_streamProvider->getInputStream(part));
|
||||
}
|
||||
|
||||
}
|
||||
@ -91,9 +92,9 @@ void StreamPartReader::onPartData(const std::shared_ptr<Part>& part, const char*
|
||||
|
||||
const char* const AsyncStreamPartReader::TAG_NAME = "[oatpp::web::mime::multipart::AsyncStreamPartReader::TAG]";
|
||||
|
||||
AsyncStreamPartReader::AsyncStreamPartReader(const std::shared_ptr<AsyncPartReaderStreamProvider>& streamProvider,
|
||||
AsyncStreamPartReader::AsyncStreamPartReader(const std::shared_ptr<AsyncPartReaderResourceProvider>& resourceProvider,
|
||||
v_io_size maxDataSize)
|
||||
: m_streamProvider(streamProvider)
|
||||
: m_resourceProvider(resourceProvider)
|
||||
, m_maxDataSize(maxDataSize)
|
||||
{}
|
||||
|
||||
@ -102,19 +103,19 @@ async::CoroutineStarter AsyncStreamPartReader::onNewPartAsync(const std::shared_
|
||||
class OnNewPartCoroutine : public async::Coroutine<OnNewPartCoroutine> {
|
||||
private:
|
||||
std::shared_ptr<Part> m_part;
|
||||
std::shared_ptr<AsyncPartReaderStreamProvider> m_streamProvider;
|
||||
std::shared_ptr<data::stream::OutputStream> m_obtainedStream;
|
||||
std::shared_ptr<AsyncPartReaderResourceProvider> m_resourceProvider;
|
||||
std::shared_ptr<data::resource::Resource> m_obtainedResource;
|
||||
public:
|
||||
|
||||
OnNewPartCoroutine(const std::shared_ptr<Part>& part,
|
||||
const std::shared_ptr<AsyncPartReaderStreamProvider>& streamProvider)
|
||||
const std::shared_ptr<AsyncPartReaderResourceProvider>& resourceProvider)
|
||||
: m_part(part)
|
||||
, m_streamProvider(streamProvider)
|
||||
, m_resourceProvider(resourceProvider)
|
||||
{}
|
||||
|
||||
Action act() override {
|
||||
|
||||
if(!m_streamProvider) {
|
||||
if(!m_resourceProvider) {
|
||||
throw std::runtime_error("[oatpp::web::mime::multipart::AsyncStreamPartReader::onNewPartAsync(){OnNewPartCoroutine}]: Error. Stream provider is nullptr.");
|
||||
}
|
||||
|
||||
@ -125,20 +126,21 @@ async::CoroutineStarter AsyncStreamPartReader::onNewPartAsync(const std::shared_
|
||||
"Part tag object is not nullptr. Seems like this part is already being processed by another part reader.");
|
||||
}
|
||||
|
||||
return m_streamProvider->getOutputStreamAsync(m_part, m_obtainedStream).next(yieldTo(&OnNewPartCoroutine::onStreamObtained));
|
||||
return m_resourceProvider->getResourceAsync(m_part, m_obtainedResource).next(yieldTo(&OnNewPartCoroutine::onResourceObtained));
|
||||
|
||||
}
|
||||
|
||||
Action onStreamObtained() {
|
||||
Action onResourceObtained() {
|
||||
auto tagObject = std::make_shared<TagObject>();
|
||||
tagObject->outputStream = m_obtainedStream;
|
||||
tagObject->resource = m_obtainedResource;
|
||||
tagObject->outputStream = m_obtainedResource->openOutputStream();
|
||||
m_part->setTag(TAG_NAME, tagObject);
|
||||
return finish();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
return OnNewPartCoroutine::start(part, m_streamProvider);
|
||||
return OnNewPartCoroutine::start(part, m_resourceProvider);
|
||||
|
||||
}
|
||||
|
||||
@ -166,40 +168,10 @@ async::CoroutineStarter AsyncStreamPartReader::onPartDataAsync(const std::shared
|
||||
}
|
||||
return tagObject->outputStream->writeExactSizeDataAsync(data, size);
|
||||
} else {
|
||||
return onPartDone(part);
|
||||
part->setPayload(tagObject->resource);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async::CoroutineStarter AsyncStreamPartReader::onPartDone(const std::shared_ptr<Part>& part) {
|
||||
|
||||
class OnPartDoneCoroutine : public async::Coroutine<OnPartDoneCoroutine> {
|
||||
public:
|
||||
std::shared_ptr<Part> m_part;
|
||||
std::shared_ptr<AsyncPartReaderStreamProvider> m_streamProvider;
|
||||
std::shared_ptr<data::stream::InputStream> m_obtainedStream;
|
||||
public:
|
||||
|
||||
OnPartDoneCoroutine(const std::shared_ptr<Part>& part,
|
||||
const std::shared_ptr<AsyncPartReaderStreamProvider>& streamProvider)
|
||||
: m_part(part)
|
||||
, m_streamProvider(streamProvider)
|
||||
{}
|
||||
|
||||
Action act() override {
|
||||
return m_streamProvider->getInputStreamAsync(m_part, m_obtainedStream).next(yieldTo(&OnPartDoneCoroutine::onStreamObtained));
|
||||
}
|
||||
|
||||
Action onStreamObtained() {
|
||||
m_part->setDataInfo(m_obtainedStream);
|
||||
m_part->clearTag();
|
||||
return finish();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
return OnPartDoneCoroutine::start(part, m_streamProvider);
|
||||
|
||||
}
|
||||
|
||||
}}}}
|
||||
|
@ -32,82 +32,45 @@
|
||||
namespace oatpp { namespace web { namespace mime { namespace multipart {
|
||||
|
||||
/**
|
||||
* Stream provider for `StreamPartReader`.
|
||||
* Resource provider for `StreamPartReader`.
|
||||
*/
|
||||
class PartReaderStreamProvider {
|
||||
public:
|
||||
/**
|
||||
* Convenience typedef for &id:oatpp::data::stream::OutputStream;.
|
||||
*/
|
||||
typedef oatpp::data::stream::OutputStream OutputStream;
|
||||
|
||||
/**
|
||||
* Convenience typedef for &id:oatpp::data::stream::InputStream;.
|
||||
*/
|
||||
typedef oatpp::data::stream::InputStream InputStream;
|
||||
class PartReaderResourceProvider {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Default virtual destructor.
|
||||
*/
|
||||
virtual ~PartReaderStreamProvider() = default;
|
||||
virtual ~PartReaderResourceProvider() = default;
|
||||
|
||||
/**
|
||||
* Get stream to write (save) part data in.
|
||||
* Get data resource to write (save) part data in.
|
||||
* @param part
|
||||
* @return
|
||||
*/
|
||||
virtual std::shared_ptr<OutputStream> getOutputStream(const std::shared_ptr<Part>& part) = 0;
|
||||
|
||||
/**
|
||||
* Get stream to read part data from. <br>
|
||||
* This method is called after all data has been streamed to OutputStream.
|
||||
* @param part
|
||||
* @return
|
||||
*/
|
||||
virtual std::shared_ptr<InputStream> getInputStream(const std::shared_ptr<Part>& part) = 0;
|
||||
virtual std::shared_ptr<data::resource::Resource> getResource(const std::shared_ptr<Part>& part) = 0;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Async stream provider for `AsyncStreamPartReader`.
|
||||
* Async resource provider for `AsyncStreamPartReader`.
|
||||
*/
|
||||
class AsyncPartReaderStreamProvider {
|
||||
public:
|
||||
/**
|
||||
* Convenience typedef for &id:oatpp::data::stream::OutputStream;.
|
||||
*/
|
||||
typedef oatpp::data::stream::OutputStream OutputStream;
|
||||
|
||||
/**
|
||||
* Convenience typedef for &id:oatpp::data::stream::InputStream;.
|
||||
*/
|
||||
typedef oatpp::data::stream::InputStream InputStream;
|
||||
class AsyncPartReaderResourceProvider {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Default virtual destructor.
|
||||
*/
|
||||
virtual ~AsyncPartReaderStreamProvider() = default;
|
||||
virtual ~AsyncPartReaderResourceProvider() = default;
|
||||
|
||||
/**
|
||||
* Get stream to write (save) part data to.
|
||||
* Get data resource to write (save) part data in.
|
||||
* @param part
|
||||
* @param stream - put here pointer to obtained stream.
|
||||
* @param resource - put here pointer to obtained resource.
|
||||
* @return
|
||||
*/
|
||||
virtual async::CoroutineStarter getOutputStreamAsync(const std::shared_ptr<Part>& part,
|
||||
std::shared_ptr<data::stream::OutputStream>& stream) = 0;
|
||||
virtual async::CoroutineStarter getResourceAsync(const std::shared_ptr<Part>& part,
|
||||
std::shared_ptr<data::resource::Resource>& resource) = 0;
|
||||
|
||||
/**
|
||||
* Get stream to read part data from. <br>
|
||||
* This method is called after all data has been streamed to OutputStream.
|
||||
* @param part
|
||||
* @param stream - put here pointer to obtained stream.
|
||||
* @return
|
||||
*/
|
||||
virtual async::CoroutineStarter getInputStreamAsync(const std::shared_ptr<Part>& part,
|
||||
std::shared_ptr<data::stream::InputStream>& stream) = 0;
|
||||
|
||||
};
|
||||
|
||||
@ -122,21 +85,21 @@ private:
|
||||
class TagObject : public oatpp::base::Countable {
|
||||
public:
|
||||
v_io_size size = 0;
|
||||
std::shared_ptr<oatpp::data::stream::OutputStream> outputStream;
|
||||
std::shared_ptr<data::resource::Resource> resource;
|
||||
std::shared_ptr<data::stream::OutputStream> outputStream;
|
||||
};
|
||||
|
||||
private:
|
||||
std::shared_ptr<PartReaderStreamProvider> m_streamProvider;
|
||||
std::shared_ptr<PartReaderResourceProvider> m_resourceProvider;
|
||||
v_io_size m_maxDataSize;
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param streamProvider
|
||||
* @param resourceProvider
|
||||
* @param maxDataSize - use `-1` for no limit.
|
||||
*/
|
||||
StreamPartReader(const std::shared_ptr<PartReaderStreamProvider>& streamProvider,
|
||||
v_io_size maxDataSize = -1);
|
||||
StreamPartReader(const std::shared_ptr<PartReaderResourceProvider>& resourceProvider, v_io_size maxDataSize = -1);
|
||||
|
||||
/**
|
||||
* Called when new part headers are parsed and part object is created.
|
||||
@ -166,23 +129,21 @@ private:
|
||||
class TagObject : public oatpp::base::Countable {
|
||||
public:
|
||||
v_io_size size = 0;
|
||||
std::shared_ptr<oatpp::data::stream::OutputStream> outputStream;
|
||||
std::shared_ptr<data::resource::Resource> resource;
|
||||
std::shared_ptr<data::stream::OutputStream> outputStream;
|
||||
};
|
||||
|
||||
private:
|
||||
async::CoroutineStarter onPartDone(const std::shared_ptr<Part>& part);
|
||||
private:
|
||||
std::shared_ptr<AsyncPartReaderStreamProvider> m_streamProvider;
|
||||
std::shared_ptr<AsyncPartReaderResourceProvider> m_resourceProvider;
|
||||
v_io_size m_maxDataSize;
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param streamProvider
|
||||
* @param resourceProvider
|
||||
* @param maxDataSize - use `-1` for no limit.
|
||||
*/
|
||||
AsyncStreamPartReader(const std::shared_ptr<AsyncPartReaderStreamProvider>& streamProvider,
|
||||
v_io_size maxDataSize = -1);
|
||||
AsyncStreamPartReader(const std::shared_ptr<AsyncPartReaderResourceProvider>& resourceProvider, v_io_size maxDataSize = -1);
|
||||
|
||||
/**
|
||||
* Called when new part headers are parsed and part object is created.
|
||||
|
@ -28,10 +28,9 @@
|
||||
namespace oatpp { namespace web { namespace protocol { namespace http { namespace outgoing {
|
||||
|
||||
v_io_size MultipartBody::readBody(void *buffer, v_buff_size count, async::Action& action) {
|
||||
const auto& part = m_iterator.get();
|
||||
const auto& stream = part->getInputStream();
|
||||
const auto& stream = m_iterator.getPartInputStream();
|
||||
if(!stream) {
|
||||
OATPP_LOGW("[oatpp::web::protocol::http::outgoing::MultipartBody::MultipartReadCallback::readBody()]", "Warning. Part has no input stream", m_state);
|
||||
OATPP_LOGW("[oatpp::web::protocol::http::outgoing::MultipartBody::MultipartReadCallback::readBody()]", "Warning. Part has no input stream.");
|
||||
return 0;
|
||||
}
|
||||
return stream->read(buffer, count, action);
|
||||
|
@ -66,6 +66,7 @@ private:
|
||||
private:
|
||||
std::shared_ptr<Multipart> m_multipart;
|
||||
std::shared_ptr<Part> m_part;
|
||||
std::shared_ptr<data::stream::InputStream> m_partInputStream;
|
||||
bool m_isFirst;
|
||||
bool m_initialized;
|
||||
public:
|
||||
@ -73,6 +74,7 @@ private:
|
||||
PartIterator(const std::shared_ptr<Multipart>& multipart)
|
||||
: m_multipart(multipart)
|
||||
, m_part(nullptr)
|
||||
, m_partInputStream(nullptr)
|
||||
, m_isFirst(true)
|
||||
, m_initialized(false)
|
||||
{}
|
||||
@ -80,12 +82,26 @@ private:
|
||||
void init(async::Action& action) {
|
||||
if(!m_initialized) {
|
||||
m_part = m_multipart->readNextPart(action);
|
||||
m_partInputStream = nullptr;
|
||||
if(m_part) {
|
||||
auto payload = m_part->getPayload();
|
||||
if (payload) {
|
||||
m_partInputStream = payload->openInputStream();
|
||||
}
|
||||
}
|
||||
m_initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
void inc(async::Action& action) {
|
||||
m_part = m_multipart->readNextPart(action);
|
||||
m_partInputStream = nullptr;
|
||||
if(m_part) {
|
||||
auto payload = m_part->getPayload();
|
||||
if (payload) {
|
||||
m_partInputStream = payload->openInputStream();
|
||||
}
|
||||
}
|
||||
m_isFirst = false;
|
||||
}
|
||||
|
||||
@ -101,6 +117,10 @@ private:
|
||||
return m_part;
|
||||
}
|
||||
|
||||
std::shared_ptr<data::stream::InputStream> getPartInputStream() {
|
||||
return m_partInputStream;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
private:
|
||||
|
@ -78,7 +78,7 @@ void runTests() {
|
||||
OATPP_LOGD("Tests", "coroutine size=%d", sizeof(oatpp::async::AbstractCoroutine));
|
||||
OATPP_LOGD("Tests", "action size=%d", sizeof(oatpp::async::Action));
|
||||
OATPP_LOGD("Tests", "class count=%d", oatpp::data::mapping::type::ClassId::getClassCount());
|
||||
|
||||
/*
|
||||
OATPP_RUN_TEST(oatpp::test::base::CommandLineArgumentsTest);
|
||||
OATPP_RUN_TEST(oatpp::test::base::LoggerTest);
|
||||
|
||||
@ -175,7 +175,7 @@ void runTests() {
|
||||
test_port.run();
|
||||
|
||||
}
|
||||
|
||||
*/
|
||||
{
|
||||
|
||||
oatpp::test::web::FullTest test_virtual(0, 1000);
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include "oatpp/network/virtual_/server/ConnectionProvider.hpp"
|
||||
#include "oatpp/network/virtual_/Interface.hpp"
|
||||
|
||||
#include "oatpp/core/data/resource/InMemoryData.hpp"
|
||||
#include "oatpp/core/macro/component.hpp"
|
||||
|
||||
#include "oatpp-test/web/ClientServerTestRunner.hpp"
|
||||
@ -127,7 +128,7 @@ std::shared_ptr<PartList> createMultipart(const std::unordered_map<oatpp::String
|
||||
auto part = std::make_shared<oatpp::web::mime::multipart::Part>(partHeaders);
|
||||
multipart->writeNextPartSimple(part);
|
||||
part->putHeader("Content-Disposition", "form-data; name=\"" + pair.first + "\"");
|
||||
part->setDataInfo(std::make_shared<oatpp::data::stream::BufferInputStream>(pair.second));
|
||||
part->setPayload(std::make_shared<oatpp::data::resource::InMemoryData>(pair.second));
|
||||
|
||||
}
|
||||
|
||||
@ -251,10 +252,13 @@ void FullAsyncTest::onRun() {
|
||||
auto part2 = multipart->getNamedPart("value2");
|
||||
|
||||
OATPP_ASSERT(part1);
|
||||
OATPP_ASSERT(part2);
|
||||
OATPP_ASSERT(part1->getPayload());
|
||||
|
||||
OATPP_ASSERT(part1->getInMemoryData() == "Hello");
|
||||
OATPP_ASSERT(part2->getInMemoryData() == "World");
|
||||
OATPP_ASSERT(part2);
|
||||
OATPP_ASSERT(part2->getPayload());
|
||||
|
||||
OATPP_ASSERT(part1->getPayload()->getInMemoryData() == "Hello");
|
||||
OATPP_ASSERT(part2->getPayload()->getInMemoryData() == "World");
|
||||
|
||||
}
|
||||
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include "oatpp/network/virtual_/server/ConnectionProvider.hpp"
|
||||
#include "oatpp/network/virtual_/Interface.hpp"
|
||||
|
||||
#include "oatpp/core/data/resource/InMemoryData.hpp"
|
||||
#include "oatpp/core/macro/component.hpp"
|
||||
|
||||
#include "oatpp-test/web/ClientServerTestRunner.hpp"
|
||||
@ -124,7 +125,7 @@ std::shared_ptr<PartList> createMultipart(const std::unordered_map<oatpp::String
|
||||
auto part = std::make_shared<oatpp::web::mime::multipart::Part>(partHeaders);
|
||||
multipart->writeNextPartSimple(part);
|
||||
part->putHeader("Content-Disposition", "form-data; name=\"" + pair.first + "\"");
|
||||
part->setDataInfo(std::make_shared<oatpp::data::stream::BufferInputStream>(pair.second));
|
||||
part->setPayload(std::make_shared<oatpp::data::resource::InMemoryData>(pair.second));
|
||||
|
||||
}
|
||||
|
||||
@ -469,10 +470,13 @@ void FullTest::onRun() {
|
||||
auto part2 = multipart->getNamedPart("value2");
|
||||
|
||||
OATPP_ASSERT(part1);
|
||||
OATPP_ASSERT(part2);
|
||||
OATPP_ASSERT(part1->getPayload());
|
||||
|
||||
OATPP_ASSERT(part1->getInMemoryData() == "Hello");
|
||||
OATPP_ASSERT(part2->getInMemoryData() == "World");
|
||||
OATPP_ASSERT(part2);
|
||||
OATPP_ASSERT(part2->getPayload());
|
||||
|
||||
OATPP_ASSERT(part1->getPayload()->getInMemoryData() == "Hello");
|
||||
OATPP_ASSERT(part2->getPayload()->getInMemoryData() == "World");
|
||||
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,7 @@
|
||||
|
||||
#include "./DTOs.hpp"
|
||||
|
||||
#include "oatpp/web/mime/multipart/FileStreamProvider.hpp"
|
||||
#include "oatpp/web/mime/multipart/FileResourceProvider.hpp"
|
||||
#include "oatpp/web/mime/multipart/InMemoryPartReader.hpp"
|
||||
#include "oatpp/web/mime/multipart/Reader.hpp"
|
||||
#include "oatpp/web/mime/multipart/PartList.hpp"
|
||||
@ -38,6 +38,7 @@
|
||||
#include "oatpp/web/server/api/ApiController.hpp"
|
||||
#include "oatpp/parser/json/mapping/ObjectMapper.hpp"
|
||||
|
||||
#include "oatpp/core/data/resource/File.hpp"
|
||||
#include "oatpp/core/data/stream/FileStream.hpp"
|
||||
#include "oatpp/core/utils/ConversionUtils.hpp"
|
||||
#include "oatpp/core/macro/codegen.hpp"
|
||||
@ -279,14 +280,14 @@ public:
|
||||
|
||||
OATPP_ASSERT_HTTP(part1, Status::CODE_400, "part1 is empty");
|
||||
|
||||
OATPP_LOGD("Multipart", "part1='%s'", part1->getInMemoryData()->c_str());
|
||||
OATPP_LOGD("Multipart", "part1='%s'", part1->getPayload()->getInMemoryData()->c_str());
|
||||
|
||||
/* Get part by name "part2"*/
|
||||
auto filePart = multipart->getNamedPart("part2");
|
||||
|
||||
OATPP_ASSERT_HTTP(filePart, Status::CODE_400, "part2 is empty");
|
||||
|
||||
auto inputStream = filePart->getInputStream();
|
||||
auto inputStream = filePart->getPayload()->openInputStream();
|
||||
|
||||
// TODO - process file stream.
|
||||
|
||||
@ -326,9 +327,9 @@ public:
|
||||
// part->setDataInfo(std::make_shared<oatpp::data::stream::BufferInputStream>(frameData));
|
||||
|
||||
if(counter % 2 == 0) {
|
||||
part->setDataInfo(std::make_shared<oatpp::data::stream::FileInputStream>("/Users/leonid/Documents/test/frame1.jpg"));
|
||||
part->setPayload(std::make_shared<data::resource::File>("/Users/leonid/Documents/test/frame1.jpg"));
|
||||
} else {
|
||||
part->setDataInfo(std::make_shared<oatpp::data::stream::FileInputStream>("/Users/leonid/Documents/test/frame2.jpg"));
|
||||
part->setPayload(std::make_shared<data::resource::File>("/Users/leonid/Documents/test/frame2.jpg"));
|
||||
}
|
||||
|
||||
++ counter;
|
||||
|
@ -27,7 +27,7 @@
|
||||
|
||||
#include "./DTOs.hpp"
|
||||
|
||||
#include "oatpp/web/mime/multipart/FileStreamProvider.hpp"
|
||||
#include "oatpp/web/mime/multipart/FileResourceProvider.hpp"
|
||||
#include "oatpp/web/mime/multipart/InMemoryPartReader.hpp"
|
||||
#include "oatpp/web/mime/multipart/Reader.hpp"
|
||||
#include "oatpp/web/mime/multipart/PartList.hpp"
|
||||
@ -38,6 +38,7 @@
|
||||
|
||||
#include "oatpp/parser/json/mapping/ObjectMapper.hpp"
|
||||
|
||||
#include "oatpp/core/data/resource/File.hpp"
|
||||
#include "oatpp/core/data/stream/FileStream.hpp"
|
||||
#include "oatpp/core/data/stream/Stream.hpp"
|
||||
#include "oatpp/core/utils/ConversionUtils.hpp"
|
||||
@ -267,7 +268,7 @@ public:
|
||||
OATPP_ASSERT_HTTP(part1, Status::CODE_400, "part1 is empty");
|
||||
|
||||
/* Print value of "part1" */
|
||||
OATPP_LOGD("Multipart", "part1='%s'", part1->getInMemoryData()->c_str());
|
||||
OATPP_LOGD("Multipart", "part1='%s'", part1->getPayload()->getInMemoryData()->c_str());
|
||||
|
||||
/* Get multipart by name */
|
||||
auto filePart = m_multipart->getNamedPart("part2");
|
||||
@ -275,7 +276,7 @@ public:
|
||||
/* Asser part not-null */
|
||||
OATPP_ASSERT_HTTP(filePart, Status::CODE_400, "part2 is empty");
|
||||
|
||||
auto inputStream = filePart->getInputStream();
|
||||
auto inputStream = filePart->getPayload()->openInputStream();
|
||||
|
||||
// TODO - process file stream.
|
||||
|
||||
@ -325,9 +326,9 @@ public:
|
||||
// part->setDataInfo(std::make_shared<oatpp::data::stream::BufferInputStream>(frameData));
|
||||
|
||||
if(counter % 2 == 0) {
|
||||
part->setDataInfo(std::make_shared<oatpp::data::stream::FileInputStream>("/Users/leonid/Documents/test/frame1.jpg"));
|
||||
part->setPayload(std::make_shared<data::resource::File>("/Users/leonid/Documents/test/frame1.jpg"));
|
||||
} else {
|
||||
part->setDataInfo(std::make_shared<oatpp::data::stream::FileInputStream>("/Users/leonid/Documents/test/frame2.jpg"));
|
||||
part->setPayload(std::make_shared<data::resource::File>("/Users/leonid/Documents/test/frame2.jpg"));
|
||||
}
|
||||
|
||||
++ counter;
|
||||
|
@ -80,18 +80,20 @@ namespace {
|
||||
|
||||
void assertPartData(const std::shared_ptr<Part>& part, const oatpp::String& value) {
|
||||
|
||||
OATPP_ASSERT(part->getInMemoryData());
|
||||
OATPP_ASSERT(part->getInMemoryData() == value);
|
||||
auto payload = part->getPayload();
|
||||
OATPP_ASSERT(payload)
|
||||
OATPP_ASSERT(payload->getInMemoryData());
|
||||
OATPP_ASSERT(payload->getInMemoryData() == value);
|
||||
|
||||
v_int64 bufferSize = 16;
|
||||
std::unique_ptr<v_char8[]> buffer(new v_char8[bufferSize]);
|
||||
|
||||
oatpp::data::stream::ChunkedBuffer stream;
|
||||
oatpp::data::stream::transfer(part->getInputStream().get(), &stream, 0, buffer.get(), bufferSize);
|
||||
oatpp::data::stream::transfer(payload->openInputStream(), &stream, 0, buffer.get(), bufferSize);
|
||||
|
||||
oatpp::String readData = stream.toString();
|
||||
|
||||
OATPP_ASSERT(readData == part->getInMemoryData());
|
||||
OATPP_ASSERT(readData == payload->getInMemoryData());
|
||||
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user