400 指定的 XML 在语法上无效

问题描述 投票:0回答:1

我正在使用 azure-sdk-for-cpp,并且在使用 CommitBlockList 时收到 400 XML指定在语法上无效。有没有办法可以看出 XML 出了什么问题? 我尝试读取日志,没有请求正文,我不知道出了什么问题。

void TestClass::Flush()
{  
    UploadBlock();
    for (auto& task : tasks) {
        if (task.valid()) {
            task.get();
        }
    }

    tasks.clear();

    std::copy(uncomitted_blocks_ids.begin(), uncomitted_blocks_ids.end(), 
    std::back_inserter(committed_blocks_ids));


    blob_client.AsBlockBlobClient().CommitBlockList(committed_blocks_ids);

    uncomitted_blocks_ids.clear();
}

void TestClass::Close()
{     
    Flush();

    committed_blocks_ids.clear();
    uncomitted_blocks_ids.clear();
}
void TestClass::UploadBlock()
{
    auto it= m_tasks.begin();
    try {
        for(; it != m_tasks.end(); /*++it*/) {
            if(it->wait_for(std::chrono::seconds(0)) == std::future_status::ready || 
                    m_tasks.size() >= m_network_connections_max){
                it->get();
                it= m_tasks.erase(it);
            }
            else {
                ++it;
            }
        }
    }
    catch(::Azure::Storage::StorageException&) {
        tasks.erase(it);
        throw;
    }
    auto block_id = GetBlockId(std::to_string(block_count++));

    m_tasks.push_back(std::async(std::launch::async, [this, block_data= m_buffer, block_id]() {
        auto block_content = ::Azure::Core::IO::MemoryBodyStream(block_data.data(), block_data.size());

        uncomitted_blocks_ids.push_back(block_id);

        blob_client.AsBlockBlobClient().StageBlock(block_id, block_content);
    }));
}
azure azure-storage azure-sdk
1个回答
0
投票

400 使用 CommitBlockList 时指定的 XML 在语法上无效

使用

400

 时指定的 
CommitBlockList
 XML 在语法上无效错误通常表示为提交块生成的 XML 有效负载无效或格式错误。

您可以参考这两个 Microsoft 文档

DOC-1DOC-2,以在 Azure Blob 存储中上传正确的上传块 Blob。

这里我使用了示例代码,它将上传文件并更正块 ID。

代码:

#include <azure/storage/blobs.hpp> #include <fstream> #include <future> #include <iostream> #include <iomanip> #include <sstream> #include <vector> #include <chrono> #include <openssl/evp.h> // OpenSSL for Base64 encoding using namespace Azure::Storage::Blobs; const int BlockSize = 4 * 1024 * 1024; // 4 MB blocks const int MaxConcurrency = 8; class TestClass { public: TestClass(BlockBlobClient blobClient) : blob_client(blobClient), block_count(0) {} void UploadBlock(); void Flush(); void Close(); private: std::string Base64Encode(const std::string& input); std::string GetBlockId(const std::string& blockNumber); BlockBlobClient blob_client; std::vector<std::future<void>> m_tasks; // Store async tasks std::vector<std::string> uncomitted_blocks_ids; // Store uncommitted block IDs std::vector<std::string> committed_blocks_ids; // Store committed block IDs std::vector<uint8_t> m_buffer; // Buffer to hold file data int block_count; size_t m_network_connections_max = MaxConcurrency; // Max parallel uploads }; std::string TestClass::Base64Encode(const std::string& input) { size_t encoded_size = 4 * ((input.size() + 2) / 3); std::string encoded_string(encoded_size, '\0'); int len = EVP_EncodeBlock(reinterpret_cast<unsigned char*>(&encoded_string[0]), reinterpret_cast<const unsigned char*>(input.c_str()), input.size()); encoded_string.resize(len); // Adjust to the actual length return encoded_string; } std::string TestClass::GetBlockId(const std::string& blockNumber) { std::stringstream ss; ss << std::setw(8) << std::setfill('0') << blockNumber; return Base64Encode(ss.str()); // Return Base64-encoded block ID } void TestClass::UploadBlock() { // Read file content into m_buffer std::ifstream file("C:\\Users\\v-vsettu\\Downloads\\sample5.pdf", std::ios::binary | std::ios::ate); if (!file) { std::cerr << "Failed to open file." << std::endl; throw std::runtime_error("Failed to open file."); } std::streamsize file_size = file.tellg(); file.seekg(0, std::ios::beg); m_buffer.resize(file_size); if (!file.read(reinterpret_cast<char*>(m_buffer.data()), file_size)) { std::cerr << "Failed to read file." << std::endl; throw std::runtime_error("Failed to read file."); } // Split the buffer into blocks and upload int offset = 0; while (offset < file_size) { int current_block_size = std::min(BlockSize, static_cast<int>(file_size) - offset); std::vector<uint8_t> block_data(m_buffer.begin() + offset, m_buffer.begin() + offset + current_block_size); auto block_id = GetBlockId(std::to_string(block_count++)); uncomitted_blocks_ids.push_back(block_id); m_tasks.push_back(std::async(std::launch::async, [this, block_data = block_data, block_id]() { auto block_content = Azure::Core::IO::MemoryBodyStream(block_data.data(), block_data.size()); blob_client.StageBlock(block_id, block_content); })); offset += current_block_size; } } void TestClass::Flush() { // Wait for all tasks to complete for (auto& task : m_tasks) { if (task.valid()) { task.get(); } } // Clear tasks after completion m_tasks.clear(); // Commit the block list blob_client.CommitBlockList(uncomitted_blocks_ids); // Add uncommitted blocks to committed list std::copy(uncomitted_blocks_ids.begin(), uncomitted_blocks_ids.end(), std::back_inserter(committed_blocks_ids)); // Clear the uncommitted blocks list uncomitted_blocks_ids.clear(); std::cout << "Upload completed successfully." << std::endl; } void TestClass::Close() { Flush(); committed_blocks_ids.clear(); uncomitted_blocks_ids.clear(); } int main() { // Define your connection string, container/blob name, and file path. std::string connection_string = "xxxxx"; std::string container_name = "data"; std::string blob_name = "test.pdf"; // Create a BlockBlobClient using the connection string. BlobContainerClient container_client = BlobContainerClient::CreateFromConnectionString(connection_string, container_name); BlockBlobClient block_blob_client = container_client.GetBlockBlobClient(blob_name); // Create an instance of TestClass TestClass test_class(block_blob_client); // Perform the upload with parallelism. test_class.UploadBlock(); test_class.Flush(); return 0; }

输出:

Upload completed successfully.

enter image description here

传送门: enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.