add interface

This commit is contained in:
lnk
2026-04-02 16:23:15 +08:00
parent 2dab1369f3
commit ea176eceaf
6 changed files with 457 additions and 13 deletions

View File

@@ -133,6 +133,81 @@ void SendJsonAPI_web(const std::string& strUrl, //接口路径
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////下载文件流式接口
size_t req_reply_file_web(void* ptr, size_t size, size_t nmemb, void* userdata)
{
std::ofstream* out = static_cast<std::ofstream*>(userdata);
size_t total = size * nmemb;
if (out && out->is_open()) {
out->write(static_cast<const char*>(ptr), total);
}
return total;
}
bool DownloadFileAPI_web(const std::string& strUrl, // 接口路径
const std::string& code, // URL参数
const std::string& json, // POST body可为空
const std::string& save_path)// 本地保存路径
{
CURL* curl = curl_easy_init();
CURLcode res;
if (!curl) {
std::cerr << ">>> web curl init failed" << std::endl;
return false;
}
std::ofstream outFile(save_path.c_str(), std::ios::out | std::ios::binary);
if (!outFile.is_open()) {
std::cerr << ">>> open file failed: " << save_path << std::endl;
curl_easy_cleanup(curl);
return false;
}
std::string fullUrl = strUrl + "?" + code;
std::cout << ">>>file " << fullUrl << std::endl;
curl_easy_setopt(curl, CURLOPT_URL, fullUrl.c_str());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, req_reply_file_web);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &outFile);
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 10);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60);
if (!json.empty()) {
curl_easy_setopt(curl, CURLOPT_POST, 1L);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json.c_str());
}
struct curl_slist* headers = nullptr;
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
long http_code = 0;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
outFile.close();
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
if (res != CURLE_OK) {
std::cerr << "web failed, res code: " << curl_easy_strerror(res) << std::endl;
remove(save_path.c_str()); // 下载失败删除残文件
return false;
}
if (http_code != 200) {
std::cerr << "web http failed, http_code: " << http_code << std::endl;
remove(save_path.c_str());
return false;
}
std::cout << ">>> file download success: " << save_path << std::endl;
return true;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////上传文件接口
//处理文件上传响应
@@ -311,6 +386,105 @@ void Fileupload_test()
std::cout << "wavepath:" << wavepath << std::endl;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////下载文件接口通用
// 下载文件:从远端路径下载到本地,并返回本地文件路径
// 入参dev设备、remote_path远端完整路径
// 返回:本地保存路径(失败返回空字符串)
std::string getfilefromweb(const std::string& devid, const std::string& remote_path)
{
try {
terminal_dev* dev = nullptr;
{
std::lock_guard<std::mutex> lock(ledgermtx);
for (auto& d : terminal_devlist) {
if (d.terminal_id == devid) {
dev = &d;
break;
}
}
}
if (!dev) {
std::cerr << "[getfile][ERROR] dev not found, id=" << devid << std::endl;
return "";
}
//【1】清洗远端路径防止 \0 问题)
std::string clean_remote = sanitize(remote_path);
//【2】提取文件名去掉路径只保留最后一段
auto get_filename = [](const std::string& path) -> std::string {
size_t pos1 = path.find_last_of('/');
size_t pos2 = path.find_last_of('\\');
size_t pos = std::string::npos;
if (pos1 == std::string::npos) pos = pos2;
else if (pos2 == std::string::npos) pos = pos1;
else pos = std::max(pos1, pos2);
return (pos == std::string::npos) ? path : path.substr(pos + 1);
};
std::string filename = get_filename(clean_remote);
//【3】构造本地保存路径
std::string mac = sanitize(normalize_mac(dev->addr_str));
std::string save_dir = std::string(FRONT_PATH) + "/bin/upload/" + mac + "/";
if (!create_directory_recursive(save_dir)) {
std::cerr << "[getfile][ERROR] create dir failed: " << save_dir << std::endl;
return "";
}
std::string save_path = save_dir + filename;
std::cout << "[getfile] remote: " << clean_remote
<< " -> local: " << save_path << std::endl;
//【4】构造接口入参
//std::string fileContent;
std::string fullPath = "filePath=" + clean_remote;
std::cout << "[getfile] request param: " << fullPath << std::endl;
//【5】调用下载接口
if (!DownloadFileAPI_web(WEB_FILEDOWNLOAD, fullPath, "", save_path)) {
std::cerr << "[getfile][ERROR] download failed: " << clean_remote << std::endl;
return "";
}
/*SendJsonAPI_web(WEB_FILEDOWNLOAD, fullPath.c_str(), "", fileContent);
//【6】判断返回
if (fileContent.empty()) {
std::cerr << "[getfile][ERROR] download failed, empty content" << std::endl;
return "";
}
//【7】写文件
std::ofstream outFile(save_path, std::ios::out | std::ios::binary);
if (!outFile.is_open()) {
std::cerr << "[getfile][ERROR] cannot open file: " << save_path << std::endl;
return "";
}
outFile.write(fileContent.c_str(), fileContent.size());
outFile.close();*/
std::cout << "[getfile] File saved successfully: " << save_path << std::endl;
//【8】返回本地路径
return save_path;
}
catch (const std::exception& e) {
std::cerr << "[getfile][EXCEPTION] " << e.what() << std::endl;
}
catch (...) {
std::cerr << "[getfile][EXCEPTION] unknown error" << std::endl;
}
return "";
}
//////////////////////////////////////////////////////////////////////////////////////////////////////映射文件下载接口
void download_xml_for_icd(const std::string& MODEL_ID,
const std::string& TMNL_TYPE,