mirror of
https://github.com/pocoproject/poco.git
synced 2025-10-23 00:07:59 +02:00
* Multipart form content length calculation
* HTMLForm test
This commit is contained in:
@@ -36,6 +36,7 @@
|
||||
|
||||
#include "Poco/Net/FilePartSource.h"
|
||||
#include "Poco/Path.h"
|
||||
#include "Poco/File.h"
|
||||
#include "Poco/Exception.h"
|
||||
|
||||
|
||||
@@ -48,7 +49,7 @@ namespace Net {
|
||||
|
||||
|
||||
FilePartSource::FilePartSource(const std::string& path):
|
||||
_istr(path)
|
||||
_path(path), _istr(path)
|
||||
{
|
||||
Path p(path);
|
||||
_filename = p.getFileName();
|
||||
@@ -59,6 +60,7 @@ FilePartSource::FilePartSource(const std::string& path):
|
||||
|
||||
FilePartSource::FilePartSource(const std::string& path, const std::string& mediaType):
|
||||
PartSource(mediaType),
|
||||
_path(path),
|
||||
_istr(path)
|
||||
{
|
||||
Path p(path);
|
||||
@@ -70,6 +72,7 @@ FilePartSource::FilePartSource(const std::string& path, const std::string& media
|
||||
|
||||
FilePartSource::FilePartSource(const std::string& path, const std::string& filename, const std::string& mediaType):
|
||||
PartSource(mediaType),
|
||||
_path(path),
|
||||
_filename(filename),
|
||||
_istr(path)
|
||||
{
|
||||
@@ -96,4 +99,11 @@ const std::string& FilePartSource::filename() const
|
||||
}
|
||||
|
||||
|
||||
std::streamsize FilePartSource::getContentLength() const
|
||||
{
|
||||
Poco::File p(_path);
|
||||
return p.getSize();
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Net
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
#include "Poco/StreamCopier.h"
|
||||
#include "Poco/URI.h"
|
||||
#include "Poco/String.h"
|
||||
#include "Poco/CountingStream.h"
|
||||
#include <sstream>
|
||||
|
||||
|
||||
@@ -61,8 +62,21 @@ namespace Poco {
|
||||
namespace Net {
|
||||
|
||||
|
||||
const std::string HTMLForm::ENCODING_URL = "application/x-www-form-urlencoded";
|
||||
const std::string HTMLForm::ENCODING_MULTIPART = "multipart/form-data";
|
||||
const std::string HTMLForm::ENCODING_URL = "application/x-www-form-urlencoded";
|
||||
const std::string HTMLForm::ENCODING_MULTIPART = "multipart/form-data";
|
||||
const int HTMLForm::UNKNOWN_CONTENT_LENGTH = -1;
|
||||
|
||||
|
||||
class HTMLFormCountingOutputStream : public CountingOutputStream
|
||||
{
|
||||
public:
|
||||
HTMLFormCountingOutputStream() : _isvalid(true) {}
|
||||
|
||||
bool getIsValid() const { return _isvalid; }
|
||||
void setIsValid(bool v) { _isvalid = v; }
|
||||
private:
|
||||
bool _isvalid;
|
||||
};
|
||||
|
||||
|
||||
HTMLForm::HTMLForm():
|
||||
@@ -237,6 +251,20 @@ void HTMLForm::prepareSubmit(HTTPRequest& request)
|
||||
}
|
||||
|
||||
|
||||
std::streamsize HTMLForm::calculateContentLength()
|
||||
{
|
||||
if (_boundary.empty())
|
||||
throw HTMLFormException("Form must be prepared");
|
||||
|
||||
HTMLFormCountingOutputStream c;
|
||||
write(c);
|
||||
if (c.getIsValid())
|
||||
return c.chars();
|
||||
else
|
||||
return UNKNOWN_CONTENT_LENGTH;
|
||||
}
|
||||
|
||||
|
||||
void HTMLForm::write(std::ostream& ostr, const std::string& boundary)
|
||||
{
|
||||
if (_encoding == ENCODING_URL)
|
||||
@@ -358,6 +386,8 @@ void HTMLForm::writeUrl(std::ostream& ostr)
|
||||
|
||||
void HTMLForm::writeMultipart(std::ostream& ostr)
|
||||
{
|
||||
HTMLFormCountingOutputStream *costr(dynamic_cast<HTMLFormCountingOutputStream*>(&ostr));
|
||||
|
||||
MultipartWriter writer(ostr, _boundary);
|
||||
for (NameValueCollection::ConstIterator it = begin(); it != end(); ++it)
|
||||
{
|
||||
@@ -385,7 +415,17 @@ void HTMLForm::writeMultipart(std::ostream& ostr)
|
||||
header.set("Content-Disposition", disp);
|
||||
header.set("Content-Type", ita->pSource->mediaType());
|
||||
writer.nextPart(header);
|
||||
StreamCopier::copyStream(ita->pSource->stream(), ostr);
|
||||
if (costr)
|
||||
{
|
||||
// count only, don't move stream position
|
||||
std::streamsize partlen = ita->pSource->getContentLength();
|
||||
if (partlen != PartSource::UNKNOWN_CONTENT_LENGTH)
|
||||
costr->addChars(partlen);
|
||||
else
|
||||
costr->setIsValid(false);
|
||||
}
|
||||
else
|
||||
StreamCopier::copyStream(ita->pSource->stream(), ostr);
|
||||
}
|
||||
writer.close();
|
||||
_boundary = writer.boundary();
|
||||
|
||||
@@ -41,6 +41,9 @@ namespace Poco {
|
||||
namespace Net {
|
||||
|
||||
|
||||
const int PartSource::UNKNOWN_CONTENT_LENGTH = -1;
|
||||
|
||||
|
||||
PartSource::PartSource():
|
||||
_mediaType("application/octet-stream")
|
||||
{
|
||||
@@ -69,5 +72,9 @@ const std::string& PartSource::filename() const
|
||||
return EMPTY;
|
||||
}
|
||||
|
||||
std::streamsize PartSource::getContentLength() const
|
||||
{
|
||||
return UNKNOWN_CONTENT_LENGTH;
|
||||
}
|
||||
|
||||
} } // namespace Poco::Net
|
||||
|
||||
@@ -80,4 +80,10 @@ const std::string& StringPartSource::filename() const
|
||||
}
|
||||
|
||||
|
||||
std::streamsize StringPartSource::getContentLength() const
|
||||
{
|
||||
return _istr.str().length();
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Net
|
||||
|
||||
Reference in New Issue
Block a user