Mercurial > hg > orthanc
comparison UnitTests/ServerIndex.cpp @ 208:de640de989b8
HttpFileSender
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 28 Nov 2012 17:00:46 +0100 |
parents | 7f74209ea0f8 |
children | 9960642f0f45 |
comparison
equal
deleted
inserted
replaced
207:7f74209ea0f8 | 208:de640de989b8 |
---|---|
2 | 2 |
3 #include "../OrthancServer/DatabaseWrapper.h" | 3 #include "../OrthancServer/DatabaseWrapper.h" |
4 | 4 |
5 #include <ctype.h> | 5 #include <ctype.h> |
6 #include <glog/logging.h> | 6 #include <glog/logging.h> |
7 | |
8 | 7 |
9 using namespace Orthanc; | 8 using namespace Orthanc; |
10 | 9 |
11 namespace | 10 namespace |
12 { | 11 { |
259 ASSERT_EQ("", listener.ancestorId_); // No more ancestor | 258 ASSERT_EQ("", listener.ancestorId_); // No more ancestor |
260 } | 259 } |
261 | 260 |
262 | 261 |
263 | 262 |
263 | |
264 #include "../Core/HttpServer/FilesystemHttpSender.h" | |
265 | |
264 #include "../Core/Toolbox.h" | 266 #include "../Core/Toolbox.h" |
265 #include "../Core/HttpServer/HttpOutput.h" | 267 #include "../Core/HttpServer/HttpOutput.h" |
266 #include "../Core/HttpServer/HttpHandler.h" | 268 #include "../Core/HttpServer/HttpHandler.h" |
269 | |
270 #include "../Core/HttpServer/HttpFileSender.h" | |
271 | |
267 | 272 |
268 namespace Orthanc | 273 namespace Orthanc |
269 { | 274 { |
270 class RestApiPath | 275 class RestApiPath |
271 { | 276 { |
371 bool Match(const UriComponents& uri) const | 376 bool Match(const UriComponents& uri) const |
372 { | 377 { |
373 Components components; | 378 Components components; |
374 UriComponents trailing; | 379 UriComponents trailing; |
375 return Match(components, trailing, uri); | 380 return Match(components, trailing, uri); |
376 } | |
377 }; | |
378 | |
379 | |
380 class HttpFileSender | |
381 { | |
382 private: | |
383 std::string contentType_; | |
384 std::string filename_; | |
385 | |
386 void SendHeader(HttpOutput& output) | |
387 { | |
388 std::string header; | |
389 header += "Content-Length: " + boost::lexical_cast<std::string>(GetFileSize()) + "\r\n"; | |
390 | |
391 if (contentType_.size() > 0) | |
392 { | |
393 header += "Content-Type: " + contentType_ + "\r\n"; | |
394 } | |
395 | |
396 if (filename_.size() > 0) | |
397 { | |
398 header += "Content-Disposition: attachment; filename=\"" + filename_ + "\"\r\n"; | |
399 } | |
400 | |
401 output.SendCustomOkHeader(header); | |
402 } | |
403 | |
404 protected: | |
405 virtual uint64_t GetFileSize() = 0; | |
406 | |
407 virtual bool SendData(HttpOutput& output) = 0; | |
408 | |
409 public: | |
410 virtual ~HttpFileSender() | |
411 { | |
412 } | |
413 | |
414 void ResetContentType() | |
415 { | |
416 contentType_.clear(); | |
417 } | |
418 | |
419 void SetContentType(const std::string& contentType) | |
420 { | |
421 contentType_ = contentType; | |
422 } | |
423 | |
424 const std::string& GetContentType() const | |
425 { | |
426 return contentType_; | |
427 } | |
428 | |
429 void ResetFilename() | |
430 { | |
431 contentType_.clear(); | |
432 } | |
433 | |
434 void SetFilename(const std::string& filename) | |
435 { | |
436 filename_ = filename; | |
437 } | |
438 | |
439 const std::string& GetFilename() const | |
440 { | |
441 return filename_; | |
442 } | |
443 | |
444 void Send(HttpOutput& output) | |
445 { | |
446 SendHeader(output); | |
447 | |
448 if (!SendData(output)) | |
449 { | |
450 output.SendHeader(Orthanc_HttpStatus_500_InternalServerError); | |
451 } | |
452 } | |
453 }; | |
454 | |
455 | |
456 class FilesystemHttpSender : public HttpFileSender | |
457 { | |
458 private: | |
459 std::string path_; | |
460 | |
461 protected: | |
462 virtual uint64_t GetFileSize() | |
463 { | |
464 return Toolbox::GetFileSize(path_); | |
465 } | |
466 | |
467 virtual bool SendData(HttpOutput& output) | |
468 { | |
469 FILE* fp = fopen(path_.c_str(), "rb"); | |
470 if (!fp) | |
471 { | |
472 return false; | |
473 } | |
474 | |
475 std::vector<uint8_t> buffer(1024 * 1024); // Chunks of 1MB | |
476 | |
477 for (;;) | |
478 { | |
479 size_t nbytes = fread(&buffer[0], 1, buffer.size(), fp); | |
480 if (nbytes == 0) | |
481 { | |
482 break; | |
483 } | |
484 else | |
485 { | |
486 output.Send(&buffer[0], nbytes); | |
487 } | |
488 } | |
489 | |
490 fclose(fp); | |
491 | |
492 return true; | |
493 } | |
494 | |
495 public: | |
496 FilesystemHttpSender(const char* path) : path_(path) | |
497 { | |
498 boost::filesystem::path p(path); | |
499 SetFilename(p.filename().string()); | |
500 SetContentType(Toolbox::AutodetectMimeType(p.filename().string())); | |
501 } | 381 } |
502 }; | 382 }; |
503 | 383 |
504 | 384 |
505 class RestApiOutput | 385 class RestApiOutput |
992 | 872 |
993 httpServer.Start(); | 873 httpServer.Start(); |
994 /*LOG(WARNING) << "REST has started"; | 874 /*LOG(WARNING) << "REST has started"; |
995 Toolbox::ServerBarrier();*/ | 875 Toolbox::ServerBarrier();*/ |
996 } | 876 } |
997 | |
998 | |
999 /** | |
1000 | |
1001 output.AnswerBufferWithContentType(s, "application/json"); | |
1002 output.AnswerFile(storage_, fileUuid, contentType, filename.c_str()); | |
1003 output.Redirect("app/explorer.html"); | |
1004 output.SendHeader(Orthanc_HttpStatus_415_UnsupportedMediaType); | |
1005 output.SendMethodNotAllowedError("GET"); | |
1006 | |
1007 **/ |