[Webserver]httplib webserver+large file upload 

👉🏻 대용량 파일 업로드를 위한 설명입니다.
This is an explanation for uploading large files.

👉🏻 업로드 진행률을 확인을 할 수 있습니다.
You can check the upload progress.

👉🏻 테스트는 macOS에서 http로 테스트 했습니다.
The test was performed on macOS using http.

👉🏻 macOS에서 테스트 했지만 리눅스에서 사용해도 됩니다.
I tested it on macOS, but it can also be used on Linux.

👉🏻 리눅스에서 사용시 방화벽에서 5080포트 오픈되어야 합니다.(이전 게시물을 참조 하세요)
When using on Linux, port 5080 must be open in the firewall. (Please refer to the previous post.)

✔️ 코드 / Code

//#define CPPHTTPLIB_OPENSSL_SUPPORT // HTTPS
#include "httplib.h"
#include <filesystem>
#include <fstream>
#include <iostream>

int main() {
    // HTTP면 Server, HTTPS면 SSLServer 사용
    // Use Server for HTTP, SSLServer for HTTPS

    httplib::Server svr;

    // httplib::SSLServer svr("./fullchain.pem", "./privkey.pem"); // HTTPS

    std::filesystem::create_directories("./uploads");
    svr.set_payload_max_length(1024ULL * 1024 * 1024 * 10); // 10GB

    // Multipart 업로드 / Multipart Upload
    svr.Post("/upload/multipart", [&](const httplib::Request& req, httplib::Response& res,
                                      const httplib::ContentReader& reader) {
        if (!req.is_multipart_form_data()) {
            res.status = 400;
            res.set_content("not multipart", "text/plain");
            return;
        }

        std::ofstream ofs;
        bool ok = reader(
            [&](const httplib::FormData& part) {
                if (part.name == "file") {
                    std::string name = httplib::sanitize_filename(part.filename.empty() ? "upload.bin" : part.filename);
                    ofs.open("./uploads/" + name, std::ios::binary);
                    if (!ofs) return false;
                }
                return true;
            },
            [&](const char* data, size_t len) {
                if (ofs) ofs.write(data, static_cast<std::streamsize>(len));
                return true;
            });

        if (ofs) ofs.close();

        if (!ok) {
            res.status = 500;
            res.set_content("multipart stream failed", "text/plain");
            return;
        }

        res.set_content("multipart upload ok", "text/plain");
    });

    // 업로드 진행률 표시
    // HTML form displaying upload status
    svr.Get("/", [](const httplib::Request&, httplib::Response& res) {
        res.set_content(R"(
    <!doctype html>
    <html>
    <body>
      <h1>Upload</h1>

      <form id="uploadForm">
        <input type="file" id="file" name="file" required />
        <button type="submit">Upload</button>
      </form>

      <p id="percent">0%</p>
      <progress id="bar" value="0" max="100" style="width: 300px;"></progress>
      <pre id="result"></pre>

      <script>
        const form = document.getElementById('uploadForm');
        const bar = document.getElementById('bar');
        const percent = document.getElementById('percent');
        const result = document.getElementById('result');

        form.addEventListener('submit', (e) => {
          e.preventDefault();

          const fileInput = document.getElementById('file');
          if (!fileInput.files.length) return;

          const data = new FormData();
          data.append('file', fileInput.files[0]);

          const xhr = new XMLHttpRequest();
          xhr.open('POST', '/upload/multipart', true);

          xhr.upload.onprogress = (evt) => {
            if (evt.lengthComputable) {
              const p = Math.round((evt.loaded / evt.total) * 100);
              bar.value = p;
              percent.textContent = p + '%';
            }
          };

          xhr.onload = () => {
            result.textContent = 'status: ' + xhr.status + '\\n' + xhr.responseText;
          };

          xhr.onerror = () => {
            result.textContent = 'upload failed';
          };

          xhr.send(data);
        });
      </script>
    </body>
    </html>
    )", "text/html; charset=utf-8");
    });

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

✔️ 컴파일 / Compiling

g++ large_upload_server.cpp -o large_upload_server -std=c++17 -pthread  

✔️ 서버 실행 / Run Server

./large_upload_server
서버 실행 / Run Server

✔️ 브라우저 접속 / Browser Access

— 파일 업로드 폼 / file upload form

파일 업로드 폼 / file upload form

–파일 업로드 완료 / File upload complete

파일 업로드 완료 / File upload complete

— 업로드 상태 확인 / Check upload status

업로드 상태 확인 / Check upload status

Leave a Reply