multipart: use data::resource::Resource.

This commit is contained in:
lganzzzo 2021-10-28 05:08:47 +03:00
parent 8d342e2967
commit 9a44c1f463
16 changed files with 147 additions and 305 deletions

View File

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

View File

@ -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;
}

View File

@ -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;
};

View File

@ -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;
}

View File

@ -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;

View File

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

View File

@ -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);
}
}}}}

View File

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

View File

@ -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);

View File

@ -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:

View File

@ -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);

View File

@ -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");
}

View File

@ -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");
}

View File

@ -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;

View File

@ -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;

View File

@ -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());
}