diff OrthancFramework/Sources/HttpServer/HttpOutput.cpp @ 4672:d9942d48fea7

ZipWriter::CancelStream(), ZipWriter::GetArchiveSize() and HttpOutput::AnswerWithoutBuffering()
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 02 Jun 2021 17:35:39 +0200
parents c1f36fd13730
children 7053502fbf97
line wrap: on
line diff
--- a/OrthancFramework/Sources/HttpServer/HttpOutput.cpp	Fri May 28 18:44:00 2021 +0200
+++ b/OrthancFramework/Sources/HttpServer/HttpOutput.cpp	Wed Jun 02 17:35:39 2021 +0200
@@ -573,8 +573,7 @@
   }
 
 
-  void HttpOutput::StateMachine::StartMultipart(const std::string& subType,
-                                                const std::string& contentType)
+  void HttpOutput::StateMachine::StartStreamInternal(const std::string& contentType)
   {
     if (state_ != State_WritingHeader)
     {
@@ -620,22 +619,37 @@
       header += "Connection: close\r\n";
     }
 
-    // Possibly add the cookies
-    CheckHeadersCompatibilityWithMultipart();
-
     for (std::list<std::string>::const_iterator
            it = headers_.begin(); it != headers_.end(); ++it)
     {
       header += *it;
     }
 
+    header += ("Content-Type: " + contentType + "\r\n\r\n");
+
+    stream_.Send(true, header.c_str(), header.size());
+  }
+
+
+  void HttpOutput::StateMachine::StartMultipart(const std::string& subType,
+                                                const std::string& contentType)
+  {
+    CheckHeadersCompatibilityWithMultipart();
+
     std::string contentTypeHeader;
     PrepareMultipartMainHeader(multipartBoundary_, contentTypeHeader, subType, contentType);
     multipartContentType_ = contentType;
-    header += ("Content-Type: " + contentTypeHeader + "\r\n\r\n");
+
+    StartStreamInternal(contentTypeHeader);
+
+    state_ = State_WritingMultipart;
+  }
 
-    stream_.Send(true, header.c_str(), header.size());
-    state_ = State_WritingMultipart;
+
+  void HttpOutput::StateMachine::StartStream(const std::string& contentType)
+  {
+    StartStreamInternal(contentType);
+    state_ = State_WritingStream;
   }
 
 
@@ -736,6 +750,36 @@
   }
 
 
+  void HttpOutput::StateMachine::SendStreamItem(const void* data,
+                                                size_t size)
+  {
+    if (state_ != State_WritingStream)
+    {
+      throw OrthancException(ErrorCode_BadSequenceOfCalls);
+    }
+    else
+    {
+      if (size > 0)
+      {
+        stream_.Send(false, data, size);
+      }
+    }
+  }
+  
+
+  void HttpOutput::StateMachine::CloseStream()
+  {
+    if (state_ != State_WritingStream)
+    {
+      throw OrthancException(ErrorCode_BadSequenceOfCalls);
+    }
+    else
+    {
+      state_ = State_Done;
+    }
+  }
+
+
   static void AnswerStreamAsBuffer(HttpOutput& output,
                                    IHttpStreamAnswer& stream)
   {
@@ -860,4 +904,29 @@
     chunked.Flatten(body);
     Answer(body);
   }
+
+
+  void HttpOutput::AnswerWithoutBuffering(IHttpStreamAnswer& stream)
+  {
+    std::string contentType = stream.GetContentType();
+    if (contentType.empty())
+    {
+      contentType = MIME_BINARY;
+    }
+
+    std::string filename;
+    if (stream.HasContentFilename(filename))
+    {
+      stateMachine_.AddHeader("Content-Disposition", "filename=\"" + std::string(filename) + "\"");
+    }
+
+    stateMachine_.StartStream(contentType.c_str());
+
+    while (stream.ReadNextChunk())
+    {
+      stateMachine_.SendStreamItem(stream.GetChunkContent(), stream.GetChunkSize());
+    }
+
+    stateMachine_.CloseStream();
+  }
 }