全部文档
当前文档

暂无内容

如果没有找到您期望的内容,请尝试其他搜索词

文档中心

分块下载(C++)

最近更新时间:2024-12-05 18:44:59

以下代码用于分块下载文件和一致性校验:

#include "ks3.h"


using namespace ks3;

// CRC64多项式
const uint64_t CRC64_POLY = 0xc96c5795d7870f42;
// CRC64查找表
uint64_t crc64_table[256];

// 生成CRC64查找表
void generate_crc64_table() {
    for (uint64_t i = 0; i < 256; ++i) {
        uint64_t crc = i;
        for (int j = 0; j < 8; ++j) {
            if (crc & 1) {
                crc = (crc >> 1) ^ CRC64_POLY;
            } else {
                crc >>= 1;
            }
        }
        crc64_table[i] = crc;
    }
}

// 计算文件CRC64
uint64_t calculate_crc64(const std::string& filename) {
    std::ifstream file(filename, std::ios::binary);
    if (!file) {
        std::cerr << "无法打开文件: " << filename << std::endl;
        return 0;
    }

    uint64_t crc = 0xFFFFFFFFFFFFFFFF; // CRC初始值
    char buffer[4096]; // 缓冲区
    while (file.read(buffer, sizeof(buffer))) {
        std::streamsize bytesRead = file.gcount();
        for (std::streamsize i = 0; i < bytesRead; ++i) {
            uint8_t index = (crc ^ static_cast<uint8_t>(buffer[i])) & 0xFF;
            crc = (crc >> 8) ^ crc64_table[index];
        }
    }

    // 处理剩余的字节
    std::streamsize bytesRead = file.gcount();
    for (std::streamsize i = 0; i < bytesRead; ++i) {
        uint8_t index = (crc ^ static_cast<uint8_t>(buffer[i])) & 0xFF;
        crc = (crc >> 8) ^ crc64_table[index];
    }

    return crc ^ 0xFFFFFFFFFFFFFFFF; // 返回CRC值(取反)
}


std::string getHeaderValue(const std::string& str) {
    size_t pos = str.find('\r');
    if (pos != std::string::npos) {
        return str.substr(0, pos);
    }
    
    return str;
}


int main() {
    std::string host = "ks3-cn-beijing.ksyuncs.com";
    // 准备client上下文信息

    // 金山云主账号 AccessKey 拥有所有API的访问权限,风险很高。
    // 强烈建议您创建并使用子账号账号进行 API 访问或日常运维,请登录 https://uc.console.ksyun.com/pro/iam/#/user/list 创建子账号。
    std::string ak = "yourAccessKey"; // 填写实际的AccessKey
    std::string sk = "yourSecretKey"; // 填写实际的SecretKey
    // 填写要上传到的桶名
    std::string bucket = "yourBucketName";
    // 填写要上传到的对象名
    std::string object_key = "yourKeyName";

    sdk::KS3Client::InitGlobalCurl();

    sdk::KS3Client client(host);
    client.Init();

    sdk::ClientContext ctx;
    ctx.bucket = bucket;
    ctx.object_key = object_key;
    ctx.accesskey = ak;
    ctx.secretkey = sk;
    // head请求查看对象大小和crc值
    sdk::KS3Response head_resp;
    int code = client.HeadObject(ctx, &head_resp);
    if (code != 0) {
        std::cout << "failed to call curl with error code " << code << std::endl;
        return -1;
    }

    std::string filename = "yourFilePath"; // 填写要下载到的文件路径
    std::ofstream outFile(filename);

    long file_size = std::stol(getHeaderValue(head_resp.res_headers["Content-Length"]));
    std::string server_crc = getHeaderValue(head_resp.res_headers["x-kss-checksum-crc64ecma"]);
    // 按range分块下载到文件
    int part_num = 1;
    int part_size = 10 * 1024 * 1024;
    long remain_size = file_size;
    while (remain_size > 0) {
        std::cout << "downloading part " << part_num << std::endl;
        int download_size = (remain_size > part_size) ? part_size : remain_size;
        ctx.start_offset = (part_num - 1) * part_size;
        ctx.end_offset = ctx.start_offset + download_size - 1;
        sdk::KS3Response part_resp;
        code = client.GetObject(ctx, &part_resp);
        if (code != 0) {
            std::cout << "failed to call curl with error code " << code << std::endl;
            return -1;
        }
        // 将内容写入文件
        outFile << part_resp.content;
        remain_size -= download_size;
        part_num++;
    }

    outFile.close();

    sdk::KS3Client::DestroyGlobalCurl();
    // 开始校验CRC64
    // 生成CRC64查找表,该方法只需调用一次
    generate_crc64_table();
    // 计算本地文件CRC64值
    uint64_t client_crc = calculate_crc64(filename);
    // 比较服务器端和本地CRC64值
    if (server_crc != std::to_string(client_crc))
    {
        std::cout << "client_crc=" << client_crc << ", server_crc=" << server_crc << std::endl;
        std::cout << "download file failed" << std::endl;
        return -1;
    }

    return 0;
}

文档导读
纯净模式常规模式

纯净模式

点击可全屏预览文档内容
文档反馈