diff --git a/src/oatpp/web/mime/multipart/PartList.cpp b/src/oatpp/web/mime/multipart/PartList.cpp index 0582c2fa..16fe4b5c 100644 --- a/src/oatpp/web/mime/multipart/PartList.cpp +++ b/src/oatpp/web/mime/multipart/PartList.cpp @@ -6,7 +6,8 @@ * (_____)(__)(__)(__) |_| |_| * * - * Copyright 2018-present, Leonid Stryzhevskyi + * Copyright 2018-present, Leonid Stryzhevskyi , + * Matthias Haselmaier * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -59,11 +60,7 @@ std::shared_ptr PartList::readNextPart(async::Action& action) { void PartList::writeNextPart(const std::shared_ptr& part, async::Action& action) { if(part->getName()) { - auto it = m_namedParts.find(part->getName()); - if(it != m_namedParts.end()) { - throw std::runtime_error("[oatpp::web::mime::multipart::Multipart::addPart()]: Error. Part with such name already exists."); - } - m_namedParts.insert({part->getName(), part}); + m_namedParts[part->getName()].push_back(part); } m_parts.push_back(part); @@ -74,13 +71,24 @@ std::shared_ptr PartList::getNamedPart(const oatpp::String& name) { auto it = m_namedParts.find(name); if(it != m_namedParts.end()) { - return it->second; + return it->second.front(); } return nullptr; } +std::list> PartList::getNamedParts(const oatpp::String& name) { + + auto it = m_namedParts.find(name); + if(it != m_namedParts.end()) { + return it->second; + } + + return std::list>{}; + +} + const std::list>& PartList::getAllParts() { return m_parts; } diff --git a/src/oatpp/web/mime/multipart/PartList.hpp b/src/oatpp/web/mime/multipart/PartList.hpp index 82341956..964e2170 100644 --- a/src/oatpp/web/mime/multipart/PartList.hpp +++ b/src/oatpp/web/mime/multipart/PartList.hpp @@ -6,7 +6,8 @@ * (_____)(__)(__)(__) |_| |_| * * - * Copyright 2018-present, Leonid Stryzhevskyi + * Copyright 2018-present, Leonid Stryzhevskyi , + * Matthias Haselmaier * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,7 +35,7 @@ namespace oatpp { namespace web { namespace mime { namespace multipart { */ class PartList : public Multipart { private: - std::unordered_map> m_namedParts; + std::unordered_map>> m_namedParts; bool m_readIteratorInitialized; std::list> m_parts; std::list>::const_iterator m_iterator; @@ -74,12 +75,21 @@ public: /** * Get part by name
+ * Returns the first part if multiple parts with same name exist. * Applicable to named parts only. * @param name - &id:oatpp::String;. * @return - &id:oatpp::web::mime::multipart::Part;. */ std::shared_ptr getNamedPart(const oatpp::String& name); + /** + * Get all parts by name
+ * Applicable to named parts only. + * @param name - &id:oatpp::String;. + * @return - std::list>. + */ + std::list> getNamedParts(const oatpp::String& name); + /** * Get list of all parts. * @return - `std::list` of `std::shared_ptr` to &id:oatpp::web::mime::multipart::Part;. diff --git a/test/oatpp/web/mime/multipart/StatefulParserTest.cpp b/test/oatpp/web/mime/multipart/StatefulParserTest.cpp index 0c52c1fd..d0805a2f 100644 --- a/test/oatpp/web/mime/multipart/StatefulParserTest.cpp +++ b/test/oatpp/web/mime/multipart/StatefulParserTest.cpp @@ -6,7 +6,8 @@ * (_____)(__)(__)(__) |_| |_| * * - * Copyright 2018-present, Leonid Stryzhevskyi + * Copyright 2018-present, Leonid Stryzhevskyi , + * Matthias Haselmaier * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -52,6 +53,14 @@ namespace { "Content-Disposition: form-data; name=part3 filename=\"filename.jpg\"\r\n" "\r\n" "part3-file-binary-data\r\n" + "--12345\r\n" + "Content-Disposition: form-data; name=\"part4\"\r\n" + "\r\n" + "part4-first-value\r\n" + "--12345\r\n" + "Content-Disposition: form-data; name=\"part4\"\r\n" + "\r\n" + "part4-second-value\r\n" "--12345--\r\n" ; @@ -112,19 +121,25 @@ void StatefulParserTest::onRun() { parseStepByStep(text, "12345", listener, i); - if(multipart.count() != 3) { + if(multipart.count() != 5) { OATPP_LOGD(TAG, "TEST_DATA_1 itearation %d", i); } - OATPP_ASSERT(multipart.count() == 3); + OATPP_ASSERT(multipart.count() == 5); auto part1 = multipart.getNamedPart("part1"); auto part2 = multipart.getNamedPart("part2"); auto part3 = multipart.getNamedPart("part3"); + auto part4 = multipart.getNamedPart("part4"); + auto part4List = multipart.getNamedParts("part4"); + OATPP_ASSERT(part1); OATPP_ASSERT(part2); OATPP_ASSERT(part3); + OATPP_ASSERT(part4); + OATPP_ASSERT(part4List.size() == 2); + OATPP_ASSERT(part4List.front().get() == part4.get()); OATPP_ASSERT(part1->getFilename().get() == nullptr); OATPP_ASSERT(part2->getFilename() == "filename.txt"); @@ -133,6 +148,8 @@ void StatefulParserTest::onRun() { assertPartData(part1, "part1-value"); assertPartData(part2, "--part2-file-content-line1\r\n--1234part2-file-content-line2"); assertPartData(part3, "part3-file-binary-data"); + assertPartData(part4List.front(), "part4-first-value"); + assertPartData(part4List.back(), "part4-second-value"); }