Merge branch 'srett-fileresource-open-once' into develop
This commit is contained in:
@@ -19,8 +19,6 @@
|
|||||||
|
|
||||||
#include "FileResourceHandler.hpp"
|
#include "FileResourceHandler.hpp"
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
|
|
||||||
#include "core/ILogger.hpp"
|
#include "core/ILogger.hpp"
|
||||||
#include "core/MimeTypes.hpp"
|
#include "core/MimeTypes.hpp"
|
||||||
|
|
||||||
@@ -32,38 +30,37 @@ namespace lms::core
|
|||||||
}
|
}
|
||||||
|
|
||||||
FileResourceHandler::FileResourceHandler(const std::filesystem::path& path, std::string_view mimeType)
|
FileResourceHandler::FileResourceHandler(const std::filesystem::path& path, std::string_view mimeType)
|
||||||
: _path{ path }
|
: _mimeType{ mimeType }
|
||||||
, _mimeType{ mimeType }
|
, _ifs{ path, std::ios::in | std::ios::binary }
|
||||||
{
|
{
|
||||||
|
if (!_ifs)
|
||||||
|
LMS_LOG(UTILS, ERROR, "Cannot open file stream for " << path);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_ifs.seekg(0, std::ios::end);
|
||||||
|
if (!_ifs.fail())
|
||||||
|
_fileSize = static_cast<::uint64_t>(_ifs.tellg());
|
||||||
|
LMS_LOG(UTILS, DEBUG, "File " << path << ", fileSize = " << _fileSize);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Wt::Http::ResponseContinuation* FileResourceHandler::processRequest(const Wt::Http::Request& request, Wt::Http::Response& response)
|
Wt::Http::ResponseContinuation* FileResourceHandler::processRequest(const Wt::Http::Request& request, Wt::Http::Response& response)
|
||||||
{
|
{
|
||||||
::uint64_t startByte{ _offset };
|
if (_offset == 0)
|
||||||
std::ifstream ifs{ _path, std::ios::in | std::ios::binary };
|
|
||||||
|
|
||||||
if (startByte == 0)
|
|
||||||
{
|
{
|
||||||
if (!ifs)
|
if (!_ifs)
|
||||||
{
|
{
|
||||||
LMS_LOG(UTILS, ERROR, "Cannot open file stream for " << _path);
|
|
||||||
response.setStatus(404);
|
response.setStatus(404);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
ifs.seekg(0, std::ios::end);
|
|
||||||
const ::uint64_t fileSize{ static_cast<::uint64_t>(ifs.tellg()) };
|
|
||||||
ifs.seekg(0, std::ios::beg);
|
|
||||||
|
|
||||||
LMS_LOG(UTILS, DEBUG, "File " << _path << ", fileSize = " << fileSize);
|
|
||||||
|
|
||||||
response.addHeader("Accept-Ranges", "bytes");
|
response.addHeader("Accept-Ranges", "bytes");
|
||||||
|
|
||||||
const Wt::Http::Request::ByteRangeSpecifier ranges{ request.getRanges(fileSize) };
|
const Wt::Http::Request::ByteRangeSpecifier ranges{ request.getRanges(_fileSize) };
|
||||||
if (!ranges.isSatisfiable())
|
if (!ranges.isSatisfiable())
|
||||||
{
|
{
|
||||||
std::ostringstream contentRange;
|
std::ostringstream contentRange;
|
||||||
contentRange << "bytes */" << fileSize;
|
contentRange << "bytes */" << _fileSize;
|
||||||
response.setStatus(416); // Requested range not satisfiable
|
response.setStatus(416); // Requested range not satisfiable
|
||||||
response.addHeader("Content-Range", contentRange.str());
|
response.addHeader("Content-Range", contentRange.str());
|
||||||
|
|
||||||
@@ -76,57 +73,51 @@ namespace lms::core
|
|||||||
LMS_LOG(UTILS, DEBUG, "Range requested = " << ranges[0].firstByte() << "-" << ranges[0].lastByte());
|
LMS_LOG(UTILS, DEBUG, "Range requested = " << ranges[0].firstByte() << "-" << ranges[0].lastByte());
|
||||||
|
|
||||||
response.setStatus(206);
|
response.setStatus(206);
|
||||||
startByte = ranges[0].firstByte();
|
_offset = ranges[0].firstByte();
|
||||||
_beyondLastByte = ranges[0].lastByte() + 1;
|
_beyondLastByte = ranges[0].lastByte() + 1;
|
||||||
|
|
||||||
std::ostringstream contentRange;
|
std::ostringstream contentRange;
|
||||||
contentRange << "bytes " << startByte << "-"
|
contentRange << "bytes " << _offset << "-"
|
||||||
<< _beyondLastByte - 1 << "/" << fileSize;
|
<< _beyondLastByte - 1 << "/" << _fileSize;
|
||||||
|
|
||||||
response.addHeader("Content-Range", contentRange.str());
|
response.addHeader("Content-Range", contentRange.str());
|
||||||
response.setContentLength(_beyondLastByte - startByte);
|
response.setContentLength(_beyondLastByte - _offset);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LMS_LOG(UTILS, DEBUG, "No range requested");
|
LMS_LOG(UTILS, DEBUG, "No range requested");
|
||||||
|
|
||||||
response.setStatus(200);
|
response.setStatus(200);
|
||||||
_beyondLastByte = fileSize;
|
_beyondLastByte = _fileSize;
|
||||||
response.setContentLength(_beyondLastByte);
|
response.setContentLength(_beyondLastByte);
|
||||||
}
|
}
|
||||||
|
|
||||||
LMS_LOG(UTILS, DEBUG, "Mimetype set to '" << _mimeType << "'");
|
LMS_LOG(UTILS, DEBUG, "Mimetype set to '" << _mimeType << "'");
|
||||||
response.setMimeType(_mimeType);
|
response.setMimeType(_mimeType);
|
||||||
}
|
|
||||||
else if (!ifs)
|
|
||||||
{
|
|
||||||
LMS_LOG(UTILS, ERROR, "Cannot reopen file stream for " << _path);
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
ifs.seekg(static_cast<std::istream::pos_type>(startByte));
|
_ifs.seekg(static_cast<std::istream::pos_type>(_offset));
|
||||||
|
} // end initial response setup
|
||||||
|
|
||||||
std::vector<char> buf;
|
::uint64_t restSize = _beyondLastByte - _offset;
|
||||||
buf.resize(_chunkSize);
|
::uint64_t pieceSize = std::min(restSize, _chunkSize);
|
||||||
|
|
||||||
::uint64_t restSize = _beyondLastByte - startByte;
|
std::vector<char> buf(pieceSize);
|
||||||
::uint64_t pieceSize = buf.size() > restSize ? restSize : buf.size();
|
|
||||||
|
|
||||||
ifs.read(&buf[0], pieceSize);
|
_ifs.read(buf.data(), buf.size());
|
||||||
const ::uint64_t actualPieceSize{ static_cast<::uint64_t>(ifs.gcount()) };
|
const ::uint64_t actualPieceSize{ static_cast<::uint64_t>(_ifs.gcount()) };
|
||||||
if (actualPieceSize > 0)
|
if (actualPieceSize > 0)
|
||||||
{
|
{
|
||||||
response.out().write(&buf[0], actualPieceSize);
|
response.out().write(buf.data(), actualPieceSize);
|
||||||
LMS_LOG(UTILS, DEBUG, "Written " << actualPieceSize << " bytes, range = " << startByte << "-" << startByte + actualPieceSize - 1 << "");
|
LMS_LOG(UTILS, DEBUG, "Written " << actualPieceSize << " bytes, range = " << _offset << "-" << _offset + actualPieceSize - 1 << "");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
LMS_LOG(UTILS, DEBUG, "Written 0 byte");
|
LMS_LOG(UTILS, DEBUG, "Written 0 byte");
|
||||||
}
|
|
||||||
|
|
||||||
if (ifs.good() && actualPieceSize < restSize)
|
if (!_ifs.good())
|
||||||
|
LMS_LOG(UTILS, WARNING, "Error reading from file!");
|
||||||
|
else if (actualPieceSize < restSize)
|
||||||
{
|
{
|
||||||
_offset = startByte + actualPieceSize;
|
_offset += actualPieceSize;
|
||||||
LMS_LOG(UTILS, DEBUG, "Job not complete! Remaining range: " << _offset << "-" << _beyondLastByte - 1);
|
LMS_LOG(UTILS, DEBUG, "Job not complete! Remaining range: " << _offset << "-" << _beyondLastByte - 1);
|
||||||
|
|
||||||
return response.createContinuation();
|
return response.createContinuation();
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
#include "core/IResourceHandler.hpp"
|
#include "core/IResourceHandler.hpp"
|
||||||
|
|
||||||
@@ -38,9 +39,10 @@ namespace lms::core
|
|||||||
|
|
||||||
static constexpr std::size_t _chunkSize{ 262'144 };
|
static constexpr std::size_t _chunkSize{ 262'144 };
|
||||||
|
|
||||||
std::filesystem::path _path;
|
|
||||||
std::string _mimeType;
|
std::string _mimeType;
|
||||||
::uint64_t _beyondLastByte{};
|
::uint64_t _beyondLastByte{};
|
||||||
::uint64_t _offset{};
|
::uint64_t _offset{};
|
||||||
|
::uint64_t _fileSize{};
|
||||||
|
std::ifstream _ifs;
|
||||||
};
|
};
|
||||||
} // namespace lms::core
|
} // namespace lms::core
|
||||||
Reference in New Issue
Block a user