changeset 155:93e1b0e3b83a

filenames when downloading json/dicom
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 23 Oct 2012 15:43:46 +0200
parents 66c2605532b3
children a660e18b2360
files Core/HttpServer/HttpOutput.cpp Core/HttpServer/HttpOutput.h Core/HttpServer/MongooseServer.cpp NEWS OrthancServer/OrthancRestApi.cpp
diffstat 5 files changed, 37 insertions(+), 61 deletions(-) [+]
line wrap: on
line diff
--- a/Core/HttpServer/HttpOutput.cpp	Tue Oct 23 15:12:40 2012 +0200
+++ b/Core/HttpServer/HttpOutput.cpp	Tue Oct 23 15:43:46 2012 +0200
@@ -49,33 +49,17 @@
 
   void HttpOutput::SendOkHeader(const std::string& contentType)
   {
-    SendOkHeader(contentType.c_str(), false, 0);
-  }
-
-  void HttpOutput::SendOkHeader()
-  {
-    SendOkHeader(NULL, false, 0);
+    SendOkHeader(contentType.c_str(), false, 0, NULL);
   }
 
-  void HttpOutput::SendOkHeader(uint64_t contentLength)
-  {
-    SendOkHeader(NULL, true, contentLength);
-  }
-
-  void HttpOutput::SendOkHeader(const std::string& contentType,
-                                uint64_t contentLength)
-  {
-    SendOkHeader(contentType.c_str(), true, contentLength);
-  }
-
-
   void HttpOutput::SendOkHeader(const char* contentType,
                                 bool hasContentLength,
-                                uint64_t contentLength)
+                                uint64_t contentLength,
+                                const char* contentFilename)
   {
     std::string s = "HTTP/1.1 200 OK\r\n";
 
-    if (contentType)
+    if (contentType && contentType[0] != '\0')
     {
       s += "Content-Type: " + std::string(contentType) + "\r\n";
     }
@@ -85,6 +69,11 @@
       s += "Content-Length: " + boost::lexical_cast<std::string>(contentLength) + "\r\n";
     }
 
+    if (contentFilename && contentFilename[0] != '\0')
+    {
+      s += "Content-Disposition: attachment; filename=\"" + std::string(contentFilename) + "\"\r\n";
+    }
+
     s += "\r\n";
 
     Send(&s[0], s.size());
@@ -126,7 +115,7 @@
   void HttpOutput::AnswerBufferWithContentType(const std::string& buffer,
                                                const std::string& contentType)
   {
-    SendOkHeader(contentType.c_str(), true, buffer.size());
+    SendOkHeader(contentType.c_str(), true, buffer.size(), NULL);
     SendString(buffer);
   }
 
@@ -135,13 +124,14 @@
                                                size_t size,
                                                const std::string& contentType)
   {
-    SendOkHeader(contentType.c_str(), true, size);
+    SendOkHeader(contentType.c_str(), true, size, NULL);
     Send(buffer, size);
   }
 
 
   void HttpOutput::AnswerFileWithContentType(const std::string& path,
-                                             const std::string& contentType)
+                                             const std::string& contentType,
+                                             const char* filename)
   {
     uint64_t fileSize = Toolbox::GetFileSize(path);
   
@@ -152,7 +142,7 @@
       return;
     }
   
-    SendOkHeader(contentType.c_str(), true, fileSize);
+    SendOkHeader(contentType.c_str(), true, fileSize, filename);
 
     std::vector<uint8_t> buffer(1024 * 1024);  // Chunks of 1MB
 
@@ -173,18 +163,20 @@
   }
 
 
-  void HttpOutput::AnswerFileAutodetectContentType(const std::string& path)
+  void HttpOutput::AnswerFileAutodetectContentType(const std::string& path,
+                                                   const char* filename)
   {
-    AnswerFileWithContentType(path, Toolbox::AutodetectMimeType(path));
+    AnswerFileWithContentType(path, Toolbox::AutodetectMimeType(path), filename);
   }
 
 
   void HttpOutput::AnswerFile(const FileStorage& storage,
                               const std::string& uuid,
-                              const std::string& contentType)
+                              const std::string& contentType,
+                              const char* filename)
   {
     boost::filesystem::path p(storage.GetPath(uuid));
-    AnswerFileWithContentType(p.string(), contentType);
+    AnswerFileWithContentType(p.string(), contentType, filename);
   }
 
 
--- a/Core/HttpServer/HttpOutput.h	Tue Oct 23 15:12:40 2012 +0200
+++ b/Core/HttpServer/HttpOutput.h	Tue Oct 23 15:43:46 2012 +0200
@@ -46,7 +46,8 @@
 
     void SendOkHeader(const char* contentType,
                       bool hasContentLength,
-                      uint64_t contentLength);
+                      uint64_t contentLength,
+                      const char* contentFilename);
 
   public:
     virtual ~HttpOutput()
@@ -55,16 +56,9 @@
 
     virtual void Send(const void* buffer, size_t length) = 0;
 
-    void SendString(const std::string& s);
-
-    void SendOkHeader();
-
-    void SendOkHeader(uint64_t contentLength);
-
     void SendOkHeader(const std::string& contentType);
 
-    void SendOkHeader(const std::string& contentType,
-                      uint64_t contentLength);
+    void SendString(const std::string& s);
 
     void SendMethodNotAllowedError(const std::string& allowed);
 
@@ -73,11 +67,6 @@
 
     // Higher-level constructs to send entire files or buffers -------------------
 
-    void AnswerBuffer(const std::string& buffer)
-    {
-      AnswerBufferWithContentType(buffer, "");
-    }
-
     void AnswerBufferWithContentType(const std::string& buffer,
                                      const std::string& contentType);
 
@@ -85,25 +74,17 @@
                                      size_t size,
                                      const std::string& contentType);
 
-    void AnswerFile(const std::string& path)
-    {
-      AnswerFileWithContentType(path, "");
-    }
-
     void AnswerFileWithContentType(const std::string& path,
-                                   const std::string& contentType);
+                                   const std::string& contentType,
+                                   const char* filename = NULL);
 
-    void AnswerFileAutodetectContentType(const std::string& path); 
-
-    void AnswerFile(const FileStorage& storage,
-                    const std::string& uuid)
-    {
-      AnswerFile(storage, uuid, "");
-    }
+    void AnswerFileAutodetectContentType(const std::string& path,
+                                         const char* filename = NULL); 
 
     void AnswerFile(const FileStorage& storage,
                     const std::string& uuid,
-                    const std::string& contentType);
+                    const std::string& contentType,
+                    const char* filename = NULL);
 
     void Redirect(const std::string& path);
   };
--- a/Core/HttpServer/MongooseServer.cpp	Tue Oct 23 15:12:40 2012 +0200
+++ b/Core/HttpServer/MongooseServer.cpp	Tue Oct 23 15:43:46 2012 +0200
@@ -522,7 +522,7 @@
           return (void*) "";
 
         case PostDataStatus_Pending:
-          output.AnswerBuffer("");
+          output.AnswerBufferWithContentType(NULL, 0, "");
           return (void*) "";
 
         default:
--- a/NEWS	Tue Oct 23 15:12:40 2012 +0200
+++ b/NEWS	Tue Oct 23 15:43:46 2012 +0200
@@ -1,12 +1,13 @@
 Pending changes in the mainline
 ===============================
 
-* URI "/system"
+* Use HTTP Content-Disposition to set a filename when downloading JSON/DCM
+* URI "/system" for general information about Orthanc
 * Versioning info and help on the command line
 * Improved logging
 * Possibility of dynamic linking against jsoncpp, sqlite, boost and dmctk
 * Fix some bugs
-* Switch to 8042 port for HTTP
+* Switch to default 8042 port for HTTP
 
 
 Version 0.2.2 (2012/10/04)
--- a/OrthancServer/OrthancRestApi.cpp	Tue Oct 23 15:12:40 2012 +0200
+++ b/OrthancServer/OrthancRestApi.cpp	Tue Oct 23 15:43:46 2012 +0200
@@ -566,17 +566,19 @@
               uri[2] == "tags" || 
               uri[2] == "simplified-tags"))
     {
-      std::string fileUuid, contentType;
+      std::string fileUuid, contentType, filename;
       if (uri[2] == "file")
       {
         existingResource = index_.GetDicomFile(fileUuid, uri[1]);
         contentType = "application/dicom";
+        filename = fileUuid + ".dcm";
       }
       else if (uri[2] == "tags" ||
                uri[2] == "simplified-tags")
       {
         existingResource = index_.GetJsonFile(fileUuid, uri[1]);
         contentType = "application/json";
+        filename = fileUuid + ".json";
       }
 
       if (existingResource)
@@ -590,7 +592,7 @@
         }
         else
         {
-          output.AnswerFile(storage_, fileUuid, contentType);
+          output.AnswerFile(storage_, fileUuid, contentType, filename.c_str());
           return;
         }
       }