嘗試使用"Content-Disposition: attachment; filename=test.dat"的http頭的方式來提供文件下載功能,結果發現對於某些文件,下載的文件長度比期望的長,分析後發現,文件中的0x0D('\n')被輸出成0x0A0D("\r\n")。嘗試了各種fcgi中的各種接口,始終無果。
最終,在網上各種搜索,終於看到了一篇文章講Python調用"msvcrt.setmode(1, os.O_BINARY) " 可解決類似的問題,於是搜索想到msvcrt.setmode是否爲系統函數,C++也可調用呢,果然,在微軟官網看到C++的例子(附在後面)。
完整的使用fcgi輸出二進制的數據流的代碼如下:
#include "fcgi_stdio.h"
#include <io.h>
#include <fcntl.h>
void printBinaryFile()
{
char data[10] = {'A', 0, '\r', 'C', '\n', 'D'};
//期望文件大小爲6個字節;不調用_setmode的話,下載得到的test.dat文件爲7個字節,因爲把第五個'\n'輸出爲"\r\n"了
int result = _setmode(_fileno(stdout->stdio_stream), _O_BINARY);
if (result == -1)
{
printf("Content-type: text/html\r\n"
"\r\n");
printf("Cannot set mode");
}
else
{
printf("Content-Disposition: attachment; filename=test.dat\r\n");
printf("Content-type: application/octet-stream\r\n\r\n");
fwrite(data, 6, 1, stdout);
}
}
void main(void)
{
int count = 0;
while(FCGI_Accept() >= 0)
{
printBinaryFile();
}
}
附:
1、環境說明: windows、vs2010、fcgi2-2.4.2(CGI的C語言庫)。
2、參考鏈接
https://docs.microsoft.com/zh-cn/previous-versions/tw4k6df8(v=vs.110)
3、微軟官網上setmode的例子
// crt_setmode.c
// This program uses _setmode to change
// stdin from text mode to binary mode.
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
int main( void )
{
int result;
// Set "stdin" to have binary mode:
result = _setmode( _fileno( stdin ), _O_BINARY );
if( result == -1 )
perror( "Cannot set mode" );
else
printf( "'stdin' successfully changed to binary mode\n" );
}