add: chunk conten_provider for file download

This commit is contained in:
2021-06-03 19:08:39 +02:00
parent 3baf88ba0a
commit e79de5d92e
5 changed files with 45 additions and 13 deletions

View File

@@ -192,15 +192,32 @@ void Api::file(const httplib::Request& rq, httplib::Response& rs)
sql << fmt::format("SELECT * FROM Files WHERE hash='{}';", file), soci::into(dw); sql << fmt::format("SELECT * FROM Files WHERE hash='{}';", file), soci::into(dw);
std::ifstream fs(dw.local_path, std::ios_base::binary); auto fs = std::make_shared<std::ifstream>(dw.local_path, std::ios_base::binary | std::ios::in);
fs.seekg(0, std::ios_base::end); fs->seekg(0, std::ios_base::end);
auto size = fs.tellg(); auto size = fs->tellg();
fs.seekg(0); fs->seekg(0);
rs.body.resize(static_cast<size_t>(size));
fs.read(&rs.body[0], static_cast<std::streamsize>(size)); // rs.body.resize(static_cast<size_t>(size));
// fs.read(&rs.body[0], static_cast<std::streamsize>(size));
rs.set_header("Content-Disposition", fmt::format("attachment; filename={};", dw.filename)); rs.set_header("Content-Disposition", fmt::format("attachment; filename={};", dw.filename));
rs.set_header("content-type", fmt::format("application/{}", dw.format));
rs.set_content_provider(
static_cast<size_t>(size),
fmt::format("application/{}", dw.format).c_str(),
[file = fs](size_t offset, size_t length, httplib::DataSink& sink) mutable {
size_t size = std::min(length, (size_t)1024 * 500);
//spdlog::info("Stream offset {} length {}", offset, length);
std::vector<char> data;
data.resize(size);
file->seekg(offset);
file->read(data.data(), data.size());
sink.write(data.data(), data.size());
return true;
});
} }
catch (std::exception const& e) catch (std::exception const& e)
{ {

View File

@@ -124,12 +124,21 @@ bool Worker::download(Task& task)
args += task.format.value(); args += task.format.value();
} }
args += "--restrict-filenames";
args += task.url; args += task.url;
/* ** Download ** */ /* ** Download ** */
spdlog::debug("youtube-dl {}", fmt::join(args, " ")); spdlog::debug("youtube-dl {}", fmt::join(args, " "));
bp::child c("youtube-dl.exe", bp::args(args), bp::std_out > out, bp::std_err > err); #ifdef __linux__
constexpr std::string_view youtube_dl = "youtube-dl";
#elif _WIN32
constexpr std::string_view youtube_dl = "youtube-dl.exe";
#else
#endif
bp::child c(std::string{youtube_dl}, bp::args(args), bp::std_out > out, bp::std_err > err);
std::string destination_file; std::string destination_file;

View File

@@ -3,7 +3,7 @@ module Globals exposing (..)
api : String api : String
api = api =
"http://127.0.0.1/api/" "/api/"
apiEndpoint : String -> String apiEndpoint : String -> String
@@ -14,6 +14,9 @@ apiEndpoint path =
apiStatus : String -> String apiStatus : String -> String
apiStatus id = String.concat [apiEndpoint "status/", id] apiStatus id = String.concat [apiEndpoint "status/", id]
apiAdd : String
apiAdd = apiEndpoint "add"
apiDownloadFile : String -> String apiDownloadFile : String -> String
apiDownloadFile id = String.concat [apiEndpoint "file/", id] apiDownloadFile id = String.concat [apiEndpoint "file/", id]

View File

@@ -14,7 +14,7 @@ import Json.Decode exposing (Decoder, int, string, succeed)
import Json.Decode.Pipeline exposing (required) import Json.Decode.Pipeline exposing (required)
import Json.Encode as Encode import Json.Encode as Encode
import Html.Events exposing (onMouseOver) import Html.Events exposing (onMouseOver)
import Globals exposing(apiAdd)
type alias Form = type alias Form =
{ url : String { url : String
@@ -179,7 +179,7 @@ update navKey msg model =
if not (String.isEmpty form.url) then if not (String.isEmpty form.url) then
( model ( model
, Http.post , Http.post
{ url = "http://127.0.0.1/api/add" { url = apiAdd
, body = Http.jsonBody (formPostEncoder form) , body = Http.jsonBody (formPostEncoder form)
, expect = Http.expectJson PostResult formDecoder , expect = Http.expectJson PostResult formDecoder
} }

View File

@@ -15,5 +15,8 @@ cmake
soci:shared=True soci:shared=True
soci:with_boost=True soci:with_boost=True
soci:with_sqlite3=True soci:with_sqlite3=True
soci:with_odbc=True
soci:with_postgresql=True
[imports]
lib, *.so* -> ./bin