来源:程序员老廖

1. 项目概述

1.1 功能特性

  • 用户系统:支持用户注册、登录、登出

  • 文件管理:文件上传、下载、删除、列表展示

  • 媒体预览:视频在线播放、图片预览

  • 文件分享:支持多种分享模式(公开/提取码/指定用户)

  • 大文件优化:分块上传、断点续传

  • 流式传输:视频首帧快速播放优化

1.2 项目特色

相比普通 Web 服务器项目,本项目的亮点:

  1. 大文件上传处理:基于状态机的分块解析,支持 GB 级文件

  2. 断点续传下载:完整支持 HTTP Range 请求

  3. 视频流式优化:智能缓冲控制,首帧秒开

  4. 企业级架构:基于 muduo 的 Reactor 高性能网络框架

2. 系统架构

2.1 总体架构图

┌──────────────────────────────────────────────────────────────────────────────────────┐
│                                          HTTP Client                                 │
│                                       (Browser/移动端)                               │
└──────────────────────────────────────────────────────────────────────────────────────┘
                                               │
                                               ▼
┌──────────────────────────────────────────────────────────────────────────────────────┐
│                                      HTTP Server Layer                               │
│ ┌────────────────┐    ┌───────────────┐   ┌────────────────┐  ┌───────────────┐      │
│ │   静态文件     │    │    文件上传    │   │    文件下载    │  │   用户认证    │      │
│ │   服务器       │    │    处理器      │   │    处理器      │  │     系统      │      │
│ └────────────────┘    └───────────────┘   └────────────────┘  └───────────────┘      │ 
│                                            │                                         │
│                           ┌────────────────▼───────────────┐                         │
│                           │          HttpUploadHandler     │                         │
│                           │            (业务逻辑核心)       │                        │
│                           └────────────────┬───────────────┘                         │
└────────────────────────────────────────────┼─────────────────────────────────────────┘
                                             │
┌────────────────────────────────────────────┼─────────────────────────────────────────┐
│                                MyMuduo Network Framework                             │
│ ┌──────────────────────────────────────────▼─────────────────────────────────────┐   │
│ │                                     HttpServer                                 │   │
│ │                            (HTTP Protocol Parser & Router)                     │   │
│ └──────────────────────────────────────────┬─────────────────────────────────────┘   │
│                                            │                                         │
│ ┌──────────────────────────────────────────▼─────────────────────────────────────┐   │
│ │                                      TcpServer                                 │   │
│ │                     (Connection Management & Event Distribution)               │   │
│ └──────────────────────────────────────────┬─────────────────────────────────────┘   │
│                                            │                                         │
│ ┌──────────────────────────────────────────▼─────────────────────────────────────┐   │
│ │                                       EventLoop                                │   │
│ │                            (epoll-based Reactor Pattern)                       │   │
│ └────────────────────────────────────────────────────────────────────────────────┘   │
└──────────────────────────────────────────────────────────────────────────────────────┘
                                             │
                                             ▼
┌──────────────────────────────────────────────────────────────────────────────────────┐
│                                        Data Layer                                    │
│ ┌──────────────────────────────┐ ┌──────────────────────────────────────┐            │
│ │         MySQL 5.7+           │ │            File System               │            │
│ │         - users              │ │            - uploads/                │            │
│ │         - sessions           │ │            - filename_mapping.json   │            │
│ │         - files              │ └──────────────────────────────────────┘            │
│ │         - file_shares        │                                                     │
│ └──────────────────────────────┘                                                     │
└──────────────────────────────────────────────────────────────────────────────────────┘

2.2 模块依赖关系

                     ┌──────────────────────┐
                     │   application/       │
                     │   http_upload.cc     │
                     └───────────┬──────────┘
                                 │ 使用
                                 ▼
                     ┌──────────────────────┐
                     │     net/http/        │
                     │     HttpServer       │
                     └───────────┬──────────┘
                                 │ 依赖
                                 ▼
   ┌─────────────────────────────┼──────────────────────────┐
   ▼                             ▼                          ▼
┌────────────────┐    ┌────────────────┐    ┌────────────────────┐
│    net/        │    │   base/        │    │     third_party    │
│    TcpServer   │    │   ThreadPool   │    │     json.hpp       │
│    Buffer      │    │   Buffer       │    │                    │
│    EventLoop   │    │   Logging      │    │                    │
└────────────────┘    └────────────────┘    └────────────────────┘

2.3 网络模型架构(Reactor 模式)

当前项目采用 单 Reactor + 线程池 模型:

┌────────────────────────────────────────────────────────────────────────────────────┐
│                                   Main Thread (Reactor)                            │
│ ┌─────────────────────────────────────────────────────────────────────────────┐    │
│ │                                    EventLoop                                │    │
│ │ ┌───────────────┐      ┌────────────────┐      ┌─────────────────────┐      │    │
│ │ │      epoll    │──▶  │     Channel     │──▶  │   TcpConnection     │      │    │
│ │ │      wait     │      │    callback    │      │                     │      │    │
│ │ └───────────────┘      └────────────────┘      └───────────┬─────────┘      │    │
│ └────────────────────────────────────────────────────────────┼────────────────┘    │
└──────────────────────────────────────────────────────────────┼─────────────────────┘
                                                               │
                                                  IO Events (Read/Write/Accept)
                                                               │
                                                               ▼
┌─────────────────────────────────────────────────────────────────────────────────┐
│                                   Thread Pool (4 threads)                       │
│ ┌───────────────┐ ┌────────────────┐ ┌──────────────┐ ┌──────────────────┐      │
│ │  Worker 1     │ │  Worker 2      │ │  Worker 3    │ │    Worker 4      │      │
│ │               │ │                │ │              │ │                  │      │
│ │  File Upload  │ │  File Upload   │ │  User Auth   │ │   DB Query       │      │
│ │  Processing   │ │  Processing    │ │  Processing  │ │   Processing     │      │
│ └───────────────┘ └────────────────┘ └──────────────┘ └──────────────────┘      │
│                                                                                 │
│                                   Business Logic Processing                     │
└─────────────────────────────────────────────────────────────────────────────────┘

项目代码领取:C++ Linux学完后做什么项目?推荐做C++ Linux云存储项目(附带完整项目源码和文档)

3. 核心技术栈

3.1 C++11 特性应用

本项目充分运用了 C++11 的现代特性:

智能指针管理资源

// TcpConnection 使用 shared_ptr 管理生命周期
using TcpConnectionPtr = std::shared_ptr<TcpConnection>;

// 连接上下文存储
std::shared_ptr<HttpContext> context = std::make_shared<HttpContext>();
conn->setContext(context);

// 弱引用避免循环引用
std::weak_ptr<TcpConnection> weakConn = conn;

右值引用与移动语义

// Buffer 类的移动构造函数优化数据传输
class Buffer {
     Buffer(Buffer&& other) noexcept;
     Buffer& operator=(Buffer&& other) noexcept;
};

// 在 HttpRequest 中使用移动减少拷贝
void appendToBody(const char* data, size_t len) {
     body_.append(data, len); // 内部使用移动语义
}

Lambda 表达式注册回调

// 设置 HTTP 请求处理回调
server.setHttpCallback(
     [handler](const TcpConnectionPtr& conn, HttpRequest& req, HttpResponse* resp) {
        return handler->onRequest(conn, req, resp);
     });

// 设置写完成回调(用于分块下载)
conn->setWriteCompleteCallback([this, downContext](const TcpConnectionPtr& connection) {
     std::string chunk;
     if (downContext->readNextChunk(chunk)) {
         connection->send(chunk);
         return true; // 继续写
     } else {
         connection->shutdown(); // 完成,关闭连接
         return true;
     }
});

原子操作与线程安全

// 活跃请求计数器(线程安全)
std::atomic<int> activeRequests_{0};

// 在多个线程中安全递增
activeRequests_.fetch_add(1, std::memory_order_relaxed);

3.2 线程与线程池

Thread 类封装

基于 pthread 封装,提供简洁的线程接口:

class Thread : noncopyable {
public:
      explicit Thread(ThreadFunc func, const std::string& name);
      void start();
      int join();
private:
    std::shared_ptr<pthread_t> pthreadId_;
    ThreadFunc func_;
};

ThreadPool 线程池

class ThreadPool : noncopyable { 
public: 
      explicit ThreadPool(const std::string& nameArg); 
      void start(int numThreads); 
      void run(Task task); // 提交任务到队列 
private: 
    std::vector<std::unique_ptr<Thread>> threads_; 
    BlockingQueue<Task> queue_; // 阻塞队列 
};

3.3 高性能组件

Buffer 高性能缓冲区

class Buffer {
    // 采用 vector<char> 作为底层存储
    // 预留 prependable 空间用于高效头部插入
    // 支持 scatter/gather IO

    std::vector<char> buffer_;
    size_t readerIndex_;
    size_t writerIndex_;

public:
   void append(const char* data, size_t len);
   void retrieve(size_t len);
   std::string retrieveAllAsString();
};

AsyncLogging 异步日志

class AsyncLogging : noncopyable { 
    // 双缓冲技术:前端缓冲 + 后端缓冲 
    // 避免日志 IO 阻塞业务线程 

    void append(const char* logline, int len); 

private: 
    BufferPtr currentBuffer_; // 当前写入缓冲 
    BufferPtr nextBuffer_; // 预备缓冲 
    BufferVector buffers_; // 待写入文件的缓冲队列 
};

4. 核心流程详解

4.1 文件上传流程

4.1.1 架构流程图

┌──────────────┐   POST /upload       ┌─────────────────┐
│   Client     │ ──────────────────▶  │   HttpServer    │
│   (Browser   │   Content-Type:      │                 │
│   /App)      │   multipart/         │                 │
└──────────────┘   form-data          └─────────┬───────┘
                                                │
                                                ▼
                                      ┌──────────────────┐
                                      │   HttpUpload     │
                                      │   Handler        │
                                      └─────────┬────────┘
                                                │
                        ┌───────────────────────┼───────────────────┐
                        │                       │                   │
                        ▼                       ▼                   ▼
                   ┌────────────┐        ┌──────────┐        ┌────────────┐
                   │  Parse     │        │  Create  │        │  Write to  │
                   │ Boundary   │ ────▶ │  Upload  │ ─────▶ │  Disk      │
                   │ Headers    │        │  Context │        │  (chunked) │
                   └────────────┘        └──────────┘        └────────────┘
                                                │
                                                ▼
                                        ┌──────────────┐
                                        │ MySQL Insert │
                                        │ Save metadata│
                                        └──────────────┘

4.1.2 详细时序图

4.1.3 状态机实现

文件上传采用状态机处理多部分表单数据:

class FileUploadContext {
public:
    enum class State {
       kExpectHeaders, // 等待解析 multipart headers
       kExpectContent, // 等待文件内容
       kExpectBoundary, // 等待下一个 boundary
       kComplete // 上传完成
    };

    void writeData(const char* data, size_t len);
    State getState() const { return state_; }
    void setState(State state) { state_ = state; }

private:
   State state_;
   std::string boundary_;
   std::ofstream file_;
   uintmax_t totalBytes_;
};

状态转换逻辑:

┌──────────────────────────────────┐
│    kExpectHeaders                │◀─────────────────┐
└─────────────────┬────────────────┘                  │
                  │ 解析到 \r\n\r\n                   │
                  ▼                                   │
┌──────────────────────────────────┐ 找到 boundary    │
│   kExpectContent                 │──────────────────┘
└─────────────────┬────────────────┘
                  │ 找到结束 boundary (--)
                  ▼
┌──────────────────────────────────┐
│     kComplete                    │
└──────────────────────────────────┘

4.1.4 关键代码解析

分块数据处理(http_upload.cc 第 540-620 行):

// 处理后续的数据块
std::string body = req.body();
if (!body.empty()) {
   switch (uploadContext->getState()) {
     case FileUploadContext::State::kExpectBoundary: {
        // 检查是否是结束边界
        std::string endBoundary = uploadContext->getBoundary() + "--";
        size_t endPos = body.find(endBoundary);
        if (endPos != std::string::npos) {
          if (endPos > 0) {
            uploadContext->writeData(body.data(), endPos);
          }
          uploadContext->setState(FileUploadContext::State::kComplete);
          break;
        }
        // 检查是否是普通边界
        size_t boundaryPos = body.find(uploadContext->getBoundary());
        if (boundaryPos != std::string::npos) {
          if (boundaryPos > 0) {
              uploadContext->writeData(body.data(), boundaryPos);
          }
          uploadContext->setState(FileUploadContext::State::kExpectContent);
        } else {
         // 没有找到边界,写入所有内容
         uploadContext->writeData(body.data(), body.size());
        }
     break;
    }
    // ... 其他状态处理
  }
}

性能优化点:

  1. 直接写入磁盘:避免内存累积,支持 GB 级大文件

  2. 边读边写:无需等待完整请求体

  3. 零拷贝优化:使用 std::vector<char> 直接写入

4.2 文件下载与断点续传

4.2.1 流程图

┌──────────────┐  GET /download/{filename}     ┌─────────────────┐
│    Client    │ ───────────────────────────▶ │   HttpServer     │
│   (Browser   │  Headers:                     │                 │
│    /App)     │  X-Session-ID: xxx            │                 │
└──────────────┘  Range: bytes=0-1023          └────────┬────────┘
                                                        │
                                                        ▼
                                                 ┌───────────────┐
                                                 │     权限检查  │
                                                 │     validate  │
                                                 │     Session   │
                                                 └───────┬───────┘
                                                         │
                                   ┌─────────────────────┼───────────────────┐
                                   │                     │                   │
                                 有权限 ▼              无权限 ▼        文件不存在 ▼
                            ┌────────────────┐   ┌──────────────┐  ┌────────────────┐
                            │    创建下载    │   │     403      │  │    404         │
                            │    上下文      │   │    Forbidden │  │    Not Found   │
                            └───────┬────────┘   └──────────────┘  └────────────────┘
                                    │
                                    ▼
                           ┌─────────────────┐
                           │   解析 Range    │
                           │    头部         │
                           └────────┬────────┘
                                    │
                                    ▼
                           ┌─────────────────┐
                           │   设置响应头    │
                           │    206/200      │
                           └────────┬────────┘
                                    │
                                    ▼
                           ┌─────────────┐         ┌─────────────────┐
                           │ 读取 1MB    │ ──────▶ │   发送数据      │
                           │ 数据块      │         │                 │
                           └─────────────┘         └────────┬────────┘
                                                            │ 写完成
                                                            │ 回调
                                                            ▼
                                                    ┌─────────────────┐
                                                    │   继续读/发送   │
                                                    │   直到文件结束  │
                                                    └─────────────────┘

4.2.2 时序图

4.2.3 断点续传实现

class FileDownContext {
public:
     // 定位到指定位置
     void seekTo(uintmax_t position) {
        file_.seekg(position);
        currentPosition_ = position;
        isComplete_ = false;
     }

     // 读取下一个数据块(1MB)
     bool readNextChunk(std::string& chunk) {
        const uintmax_t chunkSize = 1024 * 1024; // 1MB
        uintmax_t remainingBytes = fileSize_ - currentPosition_;
        uintmax_t bytesToRead = std::min(chunkSize, remainingBytes);

        if (bytesToRead == 0) {
           isComplete_ = true;
           return false;
        }

        std::vector<char> buffer(bytesToRead);
        file_.read(buffer.data(), bytesToRead);
        chunk.assign(buffer.data(), bytesToRead);
        currentPosition_ += bytesToRead;
        return true;
     }

private:
   std::ifstream file_;
   uintmax_t fileSize_;
   uintmax_t currentPosition_;
   bool isComplete_;
};

4.2.4 Range 请求处理

// 解析 Range 头部
std::string rangeHeader = req.getHeader("Range");
uintmax_t startPos = 0;
uintmax_t endPos = fileSize - 1;
bool isRangeRequest = false;

if (!rangeHeader.empty()) {
   std::regex rangeRegex("bytes=(\\d+)-(\\d*)");
   std::smatch matches;
   if (std::regex_search(rangeHeader, matches, rangeRegex)) {
      startPos = std::stoull(matches[1]);
      if (!matches[2].str().empty()) {
         endPos = std::stoull(matches[2]);
      }
      isRangeRequest = true;
   }
}

// 设置响应状态码
if (isRangeRequest) {
   resp->setStatusCode(HttpResponse::k206PartialContent);
   resp->addHeader("Content-Range",
      "bytes " + std::to_string(startPos) + "-" +
      std::to_string(endPos) + "/" + std::to_string(fileSize));
} else {
    resp->setStatusCode(HttpResponse::k200Ok);
}

// 支持断点续传的头部
resp->addHeader("Accept-Ranges", "bytes");
resp->addHeader("Content-Length", std::to_string(endPos - startPos + 1));

4.3 用户认证与 Session 管理

4.3.1 架构图

┌──────────────────────────────────────────────────────────────────────────────┐
│                                Session Management                            │
├──────────────────────────────────────────────────────────────────────────────┤
│                                                                              │
│ ┌────────────┐            ┌───────────────────┐           ┌──────────────┐   │
│ │   Login    │──────────▶│   Session         │─────────▶ │   MySQL      │   │
│ │            │            │   Created         │           │   sessions   │   │
│ └────────────┘            └─────────┬─────────┘           │   table      │   │
│                                     │                     └──────────────┘   │
│                                     │                                        │
│ ┌────────────────┐                  │ Session ID (32 chars)                  │
│ │   Client       │◀─────────────────┘  stored in:                            │
│ │                │                   - localStorage (Browser)                │
│ └───────┬────────┘                   - X-Session-ID header                   │
│         │                                                                    │
│         │ Subsequent Requests                                                │
│         │ X-Session-ID: xxx                                                  │
│         ▼                                                                    │
│ ┌────────────┐            ┌────────────┐            ┌────────────┐           │
│ │    API     │─────────▶ │   Validate │─────────▶  │   Update   │           │
│ │    Request │            │   Session  │            │    Expire  │           │
│ └────────────┘            └──────┬─────┘            │    Time    │           │
│                                  │                  └────────────┘           │
│                            Valid / Invalid                                   │
│                                  │                                           │
│               ┌──────────────────┼──────────────────┐                        │
│               ▼                  ▼                  ▼                        │
│           Continue 401     Unauthorized 403     Forbidden                    │
│           Processing                                                         │
│                                                                              │
└──────────────────────────────────────────────────────────────────────────────┘

4.3.2 登录时序图

4.3.3 Session 验证时序图

4.3.4 核心代码实现

Session ID 生成(http_upload.cc 第 1421-1435 行):

std::string generateSessionId() {
   std::random_device rd;
   std::mt19937 gen(rd());
   std::uniform_int_distribution<> dis(0, 35);

   const char* chars = "abcdefghijklmnopqrstuvwxyz0123456789";
   std::string sessionId;
   sessionId.reserve(32);

   for (int i = 0; i < 32; ++i) {
     sessionId += chars[dis(gen)];
   }
   return sessionId;
}

Session 验证(http_upload.cc 第 1449-1479 行):

bool validateSession(const std::string& sessionId, int& userId, std::string& username) {
   if (sessionId.empty()) {
      return false;
   }

   // 查询未过期的会话
   std::string query = "SELECT user_id, username FROM sessions WHERE session_id = '" +
                       escapeString(sessionId) + "' AND expire_time > NOW()";

   MYSQL_RES* result = executeQueryWithResult(query);
   if (!result || mysql_num_rows(result) == 0) {
      return false;
   }

   MYSQL_ROW row = mysql_fetch_row(result);
   userId = std::stoi(row[0]);
   username = row[1];
   mysql_free_result(result);

   // 更新过期时间(滑动过期)
   std::string updateQuery = "UPDATE sessions SET expire_time = DATE_ADD(NOW(), INTERVAL 30 MINUTE) WHERE session_id = '" +
                           escapeString(sessionId) + "'";
   executeQuery(updateQuery);
   return true;
}

4.4 文件分享机制

4.4.1 分享类型说明

分享类型

说明

访问方式

private

私有,不分享

仅文件所有者

public

完全公开

任何人通过链接访问

protected

需要提取码

链接 + 6位提取码

use

指定用户

仅指定用户可访问

4.4.2 分享流程图

┌───────────────────────────────────────────────────────────────────────────────┐
│                                    File Share Flow                            │
├───────────────────────────────────────────────────────────────────────────────┤
│                                                                               │
│ 1. 创建分享                                                                   │
│ ┌───────────────┐        ┌────────────────┐         ┌────────────────┐        │
│ │   用户选择    │───────▶│   生成         │───────▶ │  写入          │        │
│ │   分享类型    │        │   shareCode    │          │  file_shares  │        │
│ │   设置过期    │        │   extract      │          │  表           │        │
│ │   时间        │        │   Code(保护)   │          │               │        │
│ └───────────────┘        └────────────────┘         └────────────────┘        │
│                                     │                                         │
│                                     ▼                                         │
│                           ┌─────────────────┐                                 │
│                           │  返回分享链接    │                                │
│                           │  /share/{code}  │                                 │
│                           └─────────────────┘                                 │
│                                                                               │
│ 2. 访问分享                                                                   │
│ ┌──────────────┐       ┌──────────────┐       ┌──────────────┐                │
│ │  访问链接    │──────▶│   查询       │──────▶│  权限检查    │                │
│ │  /share/xx   │       │   shareCode  │       │              │                │
│ └──────────────┘       └──────────────┘       └───────┬──────┘                │
│                                                       │                       │
│                                           ┌───────────┼────────────┐          │
│                                           ▼           ▼            ▼          │
│                                        公开文件    需要提取码    指定用户      │
│                                           │           │            │          │
│                                           ▼           ▼            ▼          │
│                                       直接访问    验证extract    验证用户      │
│                                                                  Code 身份    │
│                                                                               │
└───────────────────────────────────────────────────────────────────────────────┘

4.4.3 分享时序图

4.5 视频流式传输优化

4.5.1 问题背景

传统视频下载会导致:

  1. 用户需要等待整个文件下载完成才能播放

  2. 大视频文件消耗大量带宽

  3. 用户可能只看几秒钟就关闭

4.5.2 优化方案

┌────────────────────────────────────────────────────────────────────┐
│                       Video Streaming Optimization                 │
├────────────────────────────────────────────────────────────────────┤
│                                                                    │
│ 传统方式 优化后                                                     │
│ ┌───────────────┐                   ┌──────────────────┐           │
│ │  下载整个     │  10秒+ 才能播放    │    首帧缓冲      │ 1秒内     │
│ │  文件         │                   │     2-5秒        │ 播放      │
│ │  (100MB)      │                   │                  │           │
│ └───────────────┘                   └────────┬─────────┘           │
│                                              │                     │
│                                              ▼                     │
│                                      ┌──────────────┐              │
│                                      │   暂停下载   │              │
│                                      │   保持连接   │              │
│                                      │   可用状态   │              │
│                                      └───────┬──────┘              │
│                                              │                     │
│                        用户点击播放 ────────▶│                     │
│                                              ▼                     │
│                                      ┌──────────────┐              │
│                                      │  恢复下载    │              │
│                                      │  流式传输    │              │
│                                      └──────────────┘              │
│                                                                    │
│ 关键技术:                                                         │
│ 1. HTTP 206 Partial Content (Range 请求)                           │
│ 2. 视频 moov atom 前置 (ffmpeg -movflags faststart)                │
│ 3. 智能缓冲控制 (metadata 加载后暂停)                               │
│                                                                    │
└────────────────────────────────────────────────────────────────────┘

4.5.3 前端缓冲控制逻辑(index.html)

// 关键代码:index.html 第 1206-1270 行
videoElement.addEventListener('loadedmetadata', function() {
    // 保存原始视频URL和时长信息
    videoElement.dataset.originalSrc = videoElement.src;
    videoElement.dataset.duration = videoElement.duration;

    // 目标缓冲时间:5秒 或 视频总时长的 10%
    const targetBufferTime = 5;
    const minBufferPercent = 0.1;
    const minBufferSeconds = Math.min(targetBufferTime, videoElement.duration * minBufferPercent);

    // 设置缓冲检查定时器
    const bufferCheckInterval = setInterval(() => {
    if (videoElement.hasAttribute('data-played')) {
       clearInterval(bufferCheckInterval);
       return;
     }

    // 检查缓冲进度
    if (videoElement.buffered.length > 0) {
       const bufferedEnd = videoElement.buffered.end(0);

       // 缓冲足够数据后中断连接
       if (bufferedEnd >= minBufferSeconds) {
         clearInterval(bufferCheckInterval);
         videoElement.pause();
         videoElement.removeAttribute('src');
         videoElement.load(); // 终止网络请求
       }
     }
  }, 500);

  // 最大等待10秒,防止无限等待
  setTimeout(() => {
     if (!videoElement.hasAttribute('data-played')) {
        clearInterval(bufferCheckInterval);
        // 至少有1秒数据就中断
        if (videoElement.buffered.length > 0 &&
            videoElement.buffered.end(0) >= 1) {
            videoElement.pause();
            videoElement.removeAttribute('src');
            videoElement.load();
        }
      }
  }, 10000);
});

// 用户点击播放时恢复下载
videoElement.addEventListener('play', function() {
    videoElement.setAttribute('data-played', 'true');
        if (!videoElement.hasAttribute('data-playing')) {
           videoElement.setAttribute('data-playing', 'true');
           if (!videoElement.src && videoElement.dataset.originalSrc) {
              videoElement.src = videoElement.dataset.originalSrc;
           }
        }
});

4.5.4 优化效果对比

指标

优化前

优化后

首帧时间

10秒+

1-3秒

初始流量消耗

100% 文件大小

2-5% 文件大小

服务器连接占用

持续直到完整下载

按需恢复

用户体验

差(长时间等待)

好(秒开播放)

5.项目运行

5.1 环境要求

操作系统:Linux (Ubuntu 18.04+ / CentOS 7+)

编译器:g++ 7.0+ (支持 C++17)

CMake:3.10+

MySQL:5.7+ 或 8.0

依赖库:

  • libmysqlclient-dev (MySQL C API)

  • nlohmann/json (单头文件 JSON 库,已包含)

5.2 数据库初始化

# 进入项目目录
# 导入数据库(替换为你的 MySQL 用户名和密码)
mysql -u root -p123456 < file_manager.sql

# 验证导入成功
mysql -u root -p123456 -e "USE file_manager; SHOW TABLES;"

5.3 编译运行

# 创建构建目录
mkdir build && cd build

# 生成构建文件
cmake ..

# 编译
make -j4

# 运行服务器
./bin/http_upload

# 访问 http://localhost:8000

5.4 配置文件说明

数据库连接配置在 http_upload.cc 中:

// HttpUploadHandler 构造函数(第 277-291 行)
HttpUploadHandler(int numThreads,
                 const std::string& dbHost = "localhost",
                 const std::string& dbUser = "root",
                 const std::string& dbPassword = "123456",
                 const std::string& dbName = "file_manager",
                 unsigned int dbPort = 3306)

修改默认配置:

// main 函数中创建 handler 时指定
auto handler = std::make_shared<HttpUploadHandler>(4, // 线程数
                                                  "localhost", // 主机
                                                  "root", // 用户名
                                                  "your_password", // 密码
                                                  "file_manager", // 数据库名
                                                  3306); // 端口

项目代码领取:C++ Linux学完后做什么项目?推荐做C++ Linux云存储项目(附带完整项目源码和文档)

更多推荐