[Webserver]httplib webserver+file upload(multipart,http)(macoOS)

👉🏻 httplib 웹서버에서 multipart 파일 업로드를 구현하는 설명입니다.
This is a description of implementing multipart file uploads on an httplib web server.

👉🏻 프로젝트 디렉토리내에 httplib.h파일을 다운 받습니다.
Download the httplib.h file into the project directory.

✔️ httplib.h(0.42.0)

curl -L https://raw.githubusercontent.com/yhirose/cpp-httplib/master/httplib.h -o httplib.h

👉🏻Http server basic (upload_server.cpp)

✔️ 아래는 cpp 클라이언트에서 로컬 서버로 파일을 업로드 하는 설명입니다.
The following is an explanation of uploading files from a C++ client to a local server.

✔️ 깃허브에서 파일 다운로드시 basic 디렉토리 내에 있는 파일 입니다.
This is the file located in the basic directory when downloading from GitHub.

✔️ 코드 / Code

— upload_server.cpp

#include "../httplib.h"
#include <fstream>
#include <iostream>

int main() {
    httplib::Server svr;

    svr.Post("/upload", [&](const httplib::Request& req, httplib::Response& res,
                            const httplib::ContentReader& content_reader) {
        if (!req.is_multipart_form_data()) {
            res.status = 400;
            res.set_content("Not multipart/form-data", "text/plain");
            return;
        }

        std::string filename;
        std::ofstream ofs;

        content_reader(
            [&](const httplib::FormData& item) {
                if (item.name != "file") return true;

                filename = httplib::sanitize_filename(item.filename);
                if (filename.empty()) {
                    res.status = 400;
                    res.set_content("Invalid filename", "text/plain");
                    return false;
                }
                // file upload directory
                ofs.open("../uploads/" + filename, std::ios::binary);
                if (!ofs) {
                    res.status = 500;
                    res.set_content("Failed to open file", "text/plain");
                    return false;
                }
                return true;
            },
            [&](const char* data, size_t len) {
                if (ofs) ofs.write(data, len);
                return true;
            }
        );

        if (ofs) ofs.close();

        res.set_content("Upload OK", "text/plain");
    });

    std::cout << "Upload server listening on http://0.0.0.0:5080\n";
    svr.listen("0.0.0.0", 5080);
}

— upload_client.cpp

#include "../httplib.h"
#include <fstream>
#include <iostream>

int main() {
    httplib::Client cli("http://localhost:5080");
 
    // 업로드 항목 / upload
    httplib::UploadFormData item;
    item.name = "file";
    item.filename = "test.txt";
    item.content_type = "text/plain";

    // 파일 읽기 / read file
    std::ifstream ifs("test.txt", std::ios::binary);
    if (!ifs) {
        std::cerr << "cannot open file\n";
        return 1;
    }
    item.content.assign((std::istreambuf_iterator<char>(ifs)),
                         std::istreambuf_iterator<char>());

    httplib::UploadFormDataItems items;
    items.push_back(item);

    httplib::Headers headers; 

    if (auto res = cli.Post("/upload", headers, items)) {
        std::cout << "status: " << res->status << "\n";
        std::cout << res->body << "\n";
    } else {
        std::cerr << "request failed\n";
    }
}

✔️ 컴파일 / Compiling

g++ upload_server.cpp -o upload_server -std=c++11

✔️ 서버 실행 / Run Server

./upload_server
서버실행 / Run Server

✔️ 컴파일 / Compiling

g++ upload_client.cpp -o upload_client -std=c++11

✔️ 클라이언트 실행 / Run Client

./upload_client
클라이언트 실행 / Run Client

✔️ 파일 업로드 상태 확인 / Check file upload status

파일 업로드 상태 확인 / Check file upload status

👉🏻Http server html (upload_server.cpp)

✔️ 아래는 html파일에서 파일을 업로드 하는 설명입니다.
Below is an explanation of how to upload a file in an HTML file.

✔️ 깃허브에서 파일 다운로드시 uploads_html 디렉토리 내에 있는 파일 입니다.
This is the file located in the uploads_html directory when downloading from GitHub.

✔️ www 디렉토리가 없으면 디렉토리를 만듦니다.
If the www directory does not exist, create the directory.

✔️ www 디렉토리 안에 간단한 index.html파일을 만듦니다.
Create a simple index.html file inside the www directory.

✔️ index.html

<!doctype html>
<html lang="ko">
    <head>
        <meta charset="utf-8" />
        <title>File Upload</title>
    </head>
    <body>
        <h1>파일 업로드/File Upload</h1>
        <form action="/upload" method="post" enctype="multipart/form-data">
            <input type="file" name="file" />
            <button type="submit">업로드/Upload</button>
        </form>
    </body>
</html>

✔️upload_server.cpp

#include "../httplib.h"
#include <fstream>
#include <iostream>
#include <sstream>

int main() {
    httplib::Server svr;

    // html upload form
    if (!svr.set_mount_point("/", "./www")) {
        std::cerr << "경로 폴더를 찾을 수 없습니다! 경로를 확인하세요./The path folder cannot be found! Please check the path." << std::endl;
        return 1;
    }

    // 업로드 처리 / Upload processing
    svr.Post("/upload", [&](const httplib::Request& req, httplib::Response& res,
                            const httplib::ContentReader& content_reader) {
        if (!req.is_multipart_form_data()) {
            res.status = 400;
            res.set_content("Not multipart/form-data", "text/plain");
            return;
        }

        std::string filename;
        std::ofstream ofs;

        content_reader(
            [&](const httplib::FormData& item) {
                if (item.name != "file") return true;

                filename = httplib::sanitize_filename(item.filename);
                if (filename.empty()) {
                    res.status = 400;
                    res.set_content("Invalid filename", "text/plain");
                    return false;
                }

                ofs.open("../uploads/" + filename, std::ios::binary);
                if (!ofs) {
                    res.status = 500;
                    res.set_content("Failed to open file", "text/plain");
                    return false;
                }
                return true;
            },
            [&](const char* data, size_t len) {
                if (ofs) ofs.write(data, len);
                return true;
            }
        );

        if (ofs) ofs.close();
        res.set_content("Upload OK", "text/plain");
    });

    std::cout << "Server listening on http://0.0.0.0:5080\n";
    svr.listen("0.0.0.0", 5080);
}

✔️ 컴파일 / Compiling

g++ upload_server.cpp -o upload_server -std=c++11

✔️ 서버실행 / Run Server

./upload_server

✔️ 브라우저 접속 / Browser access

/

upload ok

파일 업로드 상태 확인 / Check file upload status

Leave a Reply