Winsock 上的 HTTP:在用户按下浏览器中的“停止加载”按钮之前不会加载字体

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

当通过 HTTP 发送 TTF 文件时,字体不会出现,直到用户手动按下按钮停止加载页面。

我们以Inter字体为例。我使用

vector<unsigned char>
.

从磁盘读取文件到二进制文件
// Read file as binary
FILE* f;            // File handle
unsigned long flen; // File length in unsigned long because file length is always >= 0
             
f = fopen(c_internal_path, "rb"); // Open file in "r(ead)b(inary)" mode

if (!f) {   // If file not open print error to console and terminate function
    fprintf(stderr, "Unable to open file %s", c_internal_path); 
    http_code = 500;
    content = Util::stringToUCharVector(HTTP_ERROR_500);
}
else {
    fseek(f, 0, SEEK_END);
    flen = ftell(f);
    fseek(f, 0, SEEK_SET);

    content.resize(flen + 1); 
    std::fread(&content[0], flen, 1, f);

    fwrite(content.data(), 1, content.size(), stdout); // Write file contents to console
    fclose(f);

然后我取这个向量的

data()
并将其添加到输出
stringstream

// Compose HTTP response:
    std::ostringstream oss;
    oss << "HTTP/1.1 " << http_response.http_code << " OK\r\n";
    oss << "Cache-Control: no-cache, private\r\n";
    oss << "Content-Type: " << FHTTPMIME::MimeToString(mime_type) << "\r\n"; // use MimeToString() to convert enum MIME to string MIME
    oss << "Content-Length: " << http_response.content.size() << "\r\n"; // use size of 'content' vector<unsigned char>
    oss << "\r\n";
    oss << http_response.content.data(); // access vector data() for content char[]

我们得到这样的回应:

HTTP/1.1 200 OK
Cache-Control: no-cache, private
Content-Type: font/ttf
Content-Length: 803385

<binary data of the file>

然后通过以下方式将响应发送给客户端:

// Convert ostringstream to string
    std::string output = oss.str();
    int size = output.size() + 1;

// Send 'output.c_str()' char* of size 'size' to 'clientSocket'
sendToClient(clientSocket, output.c_str(), size);

文件大小为

803384
字节。在这种情况下,
ttf
字体无法正确加载,我做错了什么?

我尝试将

+1
添加到
Content-Length
和空终止(
'\0'
)二进制
vector
,但没有任何帮助。

编辑一切都按预期用于 HTML、CSS,但not 用于 TTF、JPG、JPEG、WEBP 等,即使我使用了正确的 MIME 类型。

c++ sockets vector binary winsock
1个回答
0
投票

首先,二进制数据(不是字符串)不需要终止NUL,因此删除多余的字节。

// content.resize(flen + 1);
content.resize(flen);

其次,通过

unsigned char*
运算符将
std::ostringstream
传递给
<<
使得它只需要直到第一个字节具有值
0x00
。您应该使用
write
函数来明确指定(二进制)数据的大小。

//oss << http_response.content.data();
oss.write(reinterpret_cast<char*>(http_response.content.data()), http_response.content.size());

最后,去掉另一个多余的字节。

//int size = output.size() + 1;
int size = output.size();
© www.soinside.com 2019 - 2024. All rights reserved.