最近更新时间: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;
}
纯净模式