diff --git a/postman/ZLMediaKit.postman_collection.json b/postman/ZLMediaKit.postman_collection.json index b8bbd0f7..1111850f 100644 --- a/postman/ZLMediaKit.postman_collection.json +++ b/postman/ZLMediaKit.postman_collection.json @@ -2184,6 +2184,38 @@ } }, "response": [] + }, + { + "name": "下载文件(downloadFile)", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{ZLMediaKit_URL}}/index/api/downloadFile?file_path=/path/to/file.ext", + "host": [ + "{{ZLMediaKit_URL}}" + ], + "path": [ + "index", + "api", + "downloadFile" + ], + "query": [ + { + "key": "file_path", + "value": "/path/to/file.ext", + "description": "文件绝对路径,根据文件名生成Content-Type;该接口将触发on_http_access hook" + }, + { + "key": "save_name", + "value": "test", + "description": "浏览器下载文件后保存文件名;可选参数", + "disabled": true + } + ] + } + }, + "response": [] } ], "event": [ diff --git a/server/WebApi.cpp b/server/WebApi.cpp index 58bf5627..32d01823 100755 --- a/server/WebApi.cpp +++ b/server/WebApi.cpp @@ -1809,6 +1809,30 @@ void installWebApi() { reader->startReadMP4(0, true, allArgs["file_repeat"]); }); + api_regist("/index/api/downloadFile", [](API_ARGS_MAP_ASYNC) { + CHECK_ARGS("file_path"); + + // 通过on_http_access完成文件下载鉴权,请务必确认访问鉴权url参数以及访问文件路径是否合法 + HttpSession::HttpAccessPathInvoker file_invoker = [allArgs, invoker](const string &err_msg, const string &cookie_path_in, int life_second) mutable { + if (!err_msg.empty()) { + invoker(401, StrCaseMap{}, err_msg); + } else { + StrCaseMap res_header; + auto save_name = allArgs["save_name"]; + if (!save_name.empty()) { + res_header.emplace("Content-Disposition", "attachment;filename=\"" + save_name + "\""); + } + invoker.responseFile(allArgs.getParser().getHeader(), res_header, allArgs["file_path"]); + } + }; + + bool flag = NOTICE_EMIT(BroadcastHttpAccessArgs, Broadcast::kBroadcastHttpAccess, allArgs.getParser(), allArgs["file_path"], false, file_invoker, sender); + if (!flag) { + // 文件下载鉴权事件无人监听,不允许下载 + file_invoker("None http access event listener", "", 0); + } + }); + ////////////以下是注册的Hook API//////////// api_regist("/index/hook/on_publish",[](API_ARGS_JSON){ //开始推流事件 diff --git a/src/Http/HttpFileManager.cpp b/src/Http/HttpFileManager.cpp index 1eaa9ec1..01d3c928 100644 --- a/src/Http/HttpFileManager.cpp +++ b/src/Http/HttpFileManager.cpp @@ -725,6 +725,9 @@ void HttpResponseInvokerImp::responseFile(const StrCaseMap &requestHeader, return; } + // 尝试添加Content-Type + httpHeader.emplace("Content-Type", HttpConst::getHttpContentType(file.data())); + auto &strRange = const_cast(requestHeader)["Range"]; int code = 200; if (!strRange.empty()) {