当通过 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 类型。
首先,二进制数据(不是字符串)不需要终止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();