You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用WinINet API通过HTTP PUT上传HLS音频块时出现部分上传问题

我仔细看了你的WinINet PUT上传代码,遇到这种“本地写入字节数显示正常,但服务器那边偶尔接收到不完整音频块”的随机问题,大概率是代码里的几个细节处理不到位导致的,下面给你拆解问题和修复方案:

解决WinINet PUT上传HLS音频块随机不完整的问题

1. 修复InternetWriteFile的循环逻辑错误

你的代码里这段写入循环的判断逻辑完全搞反了,这是最可能导致数据丢失的核心问题:

while(dwBytesRead < dwBytesWritten && bRet) {
    sprintf(logDump,"dwBytesRead %d dwBytesWritten %d %s",dwBytesRead,dwBytesWritten,szFile);
    WriteLog(mLogFile,logDump);
    bRet=InternetWriteFile( m_hRequest, pBuffer+dwBytesWritten, dwBytesRead - dwBytesWritten ,&dwBytesWritten);
}

正常逻辑应该是:当实际写入的字节数dwBytesWritten小于要写入的dwBytesRead时,才需要继续写入剩余数据。你现在的条件会导致本该补写剩余数据的场景直接跳过,或者错误进入循环,最终部分数据没写完就终止传输。

修正后的循环应该是这样,用一个变量跟踪总写入字节数,确保把本次读取的所有数据都写完:

DWORD totalWritten = 0;
while (totalWritten < dwBytesRead && bRet) {
    bRet = InternetWriteFile(m_hRequest, pBuffer + totalWritten, dwBytesRead - totalWritten, &dwBytesWritten);
    if (bRet) {
        totalWritten += dwBytesWritten;
        sprintf(logDump,"Written %d bytes, total %d/%d for %s", dwBytesWritten, totalWritten, dwBytesRead, szFile);
        WriteLog(mLogFile,logDump);
    } else {
        int error = GetLastError();
        sprintf(logDump,"InternetWriteFile failed with %lu while writing %s", error, szFile);
        WriteLog(mLogFile,logDump);
        bErrorFlag = true;
        break;
    }
}

2. 规范请求句柄的创建与销毁

你的m_hRequest是类成员变量,当前代码没有在每次请求结束(包括异常退出)时显式关闭它。如果上一次请求出现异常,残留的句柄可能会干扰下一次上传,引发随机问题。

建议在每个break或函数返回前,都主动清理请求句柄:

// 在每个退出分支添加:
if (m_hRequest != NULL) {
    InternetCloseHandle(m_hRequest);
    m_hRequest = NULL;
}

不要依赖CloseHTTPSession来间接清理,确保每次上传都使用全新的请求句柄。

3. 移除不必要的请求标志

你在dwFlags里添加了INTERNET_FLAG_RELOAD,这个标志的作用是强制从服务器重新获取资源,对于PUT上传请求来说完全没必要,甚至可能干扰正常的传输流程。建议去掉这个标志:

DWORD dwFlags = INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_NO_COOKIES | INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_NO_UI | INTERNET_FLAG_SECURE;

4. 增加上传后的数据校验逻辑

既然本地写入无错误但服务器接收不完整,建议在上传成功后,主动发起HEAD请求校验服务器上的文件大小,和本地文件对比,如果不一致就触发重试:

// 在HttpEndRequest成功且状态码正常后添加:
DWORD remoteSize = 0;
DWORD remoteSizeSize = sizeof(DWORD);
HINTERNET hCheckRequest = HttpOpenRequest(m_hHttpSession, "HEAD", szPostURL, "HTTP/1.1", NULL, (const char**)"*/*\0", dwFlags, 1);
if (hCheckRequest != NULL) {
    if (HttpSendRequest(hCheckRequest, NULL, 0, NULL, 0)) {
        if (HttpQueryInfo(hCheckRequest, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, &remoteSize, &remoteSizeSize, NULL)) {
            if (remoteSize != iFileSize) {
                sprintf(logDump,"Remote size %d != local size %d for %s, retrying...", remoteSize, iFileSize, szFile);
                WriteLog(mLogFile,logDump);
                bErrorFlag = true;
                // 这里可以触发重试逻辑,或者标记该文件需要重新上传
            }
        }
    }
    InternetCloseHandle(hCheckRequest);
}

5. 完善文件大小获取的校验

虽然你的音频块很小,不会触发大文件问题,但还是建议对GetFileSize的返回值做校验,避免因意外情况导致缓冲区设置错误:

DWORD fileSizeLow = GetFileSize(hFile, NULL);
if (fileSizeLow == INVALID_FILE_SIZE) {
    int error = GetLastError();
    sprintf(logDump,"GetFileSize failed with %lu for %s", error, szFile);
    WriteLog(mLogFile,logDump);
    bErrorFlag = true;
    CloseHandle(hFile);
    break;
}
BufferIn.dwBufferTotal = fileSizeLow;
iFileSize = fileSizeLow;

以上调整中,修复InternetWriteFile的循环逻辑是最关键的一步,应该能解决你遇到的随机数据不完整问题。

内容的提问来源于stack exchange,提问作者niti

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 09:02:12