这是用C编写的CGI程序的一部分。当客户端单击链接时,我希望使用建议的默认文件名开始下载该文件。
我知道规范中明确指出,内容处置标头中指定的文件名只是建议的,但无论我使用什么浏览器,它似乎总是被忽略。我认为这种行为意味着我做错了什么。
这是一个精简的代码片段,重现了我的问题。当编译为test.cgi时,程序可以工作,但浏览器将数据保存为文件名"test.cgi",而不是建议的"archive.tar.gz"。
(文件i/o错误检查和其他安全位被删除,以保持这一清晰和简短。)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#define CHUNK_SIZE 1024
int main( int argc, char *argv[] ) {
int fd;
long bytes_remaining, bytes_to_get, bytes_read, bytes_sent, retval;
int chunksize;
unsigned char data_buffer[CHUNK_SIZE];
char header_str[200];
fd = open( "archive.tar.gz", O_RDONLY );
if( fd == -1 ) {
printf( "Content-type: text/htmlnn" );
printf( "Unable to open file: %s.<br><br>n", strerror(errno) );
return 0;
}
bytes_remaining = lseek( fd, 0, SEEK_END );
lseek( fd, 0, SEEK_SET );
snprintf( header_str, 200, "Content-Type: application/x-compressedrnrnContent-Disposition: attachment; filename="archive.tar.gz"rnrn" );
write( 1, header_str, strlen(header_str) );
while( bytes_remaining > 0 ) {
if( bytes_remaining > CHUNK_SIZE ) bytes_to_get = CHUNK_SIZE;
else bytes_to_get = bytes_remaining;
bytes_read = read( fd, data_buffer, bytes_to_get );
bytes_sent = write( 1, data_buffer, bytes_read );
bytes_remaining -= bytes_sent;
}
close( fd );
return 0;
}
为什么我建议的文件名一直被忽略?
谢谢。
问题是标头中有一个额外的回车/换行。应该是:
snprintf( header_str, 200, "Content-Type: application/x-compressedrnContent-Disposition: attachment; filename=archive.tar.gzrnrn" );
正如OP中所写的,Content-Disposition行将被解释为数据的一部分,而不是标头的一部分。此外,不需要在建议的文件名周围加引号。