最近做的项目涉及到这些问题,开发web系统时有时会有以下需求,希望某类或者某已知MIME 类型的文件(比如:*.flv;*.txt;*.htm等)能够在访问时弹出“文件下载”对话框, 其次希望以原始文件名(上传时的文件名,例如:test.mp4)提供下载,但服务器上保存的地址却是其他文件名(如:test1.mp4), 希望某文件直接在浏览器上显示而不是弹出文件下载对话框.对于上面的需求,使用Content-Disposition属性就可以解决。下面是代码示例:
response.setHeader("Content-disposition", "attachment;filename=" + fileName)。
//Content-disposition为属性名。
//attachment表示以附件方式下载。如果要在页面中打开,则改为inline。
//filename如果为中文,则会出现乱码。解决办法有两种:
//1、使用fileName = new String(fileName.getBytes(), "ISO8859-1")语句
//2、使用fileName = HttpUtility.UrlEncode(filename, System.Text.Encoding.UTF8)语句
浏览器和服务器之间进行通信,是通过Socket套接字进行的,当我们在浏览器输入URL时,浏览器的后台会建立sock通信。我们现在所用的协议都是Http协议,而Http是无状态协议是这样的一个协议,用户通过浏览器向服务器发出请求,发出请求之后,浏览器是不会记住当前用户是谁,是谁希望浏览器向服务器发送服务请求的,浏览器在将服务器返回的数据呈现给用户后,Http协议会自动断开,不会一直替用户工作,因为服务器的资源是很宝贵的,监听此次请求的套接字会立即释放,然后去监听下一个请求。
要想实现服务文件下载功能就得在Content-disposition 是 MIME 协议的扩展,Content-disposition 是 MIME 协议的扩展,MIME 协议指示 MIME 用户代理如何显示附加的文件。Content-disposition其实可以控制用户请求所得的内容存为一个文件的时候提供一个默认的文件名,文件直接在浏览器上显示或者在访问时弹出文件下载对话框。 ,MIME 协议指示 MIME 用户代理如何显示附加的文件。当 Internet Explorer 接收到头时,它会激活文件下载对话框,它的文件名框自动填充了头中指定的文件名。(请注意,这是设计导致的;无法使用此功能将文档保存到用户的计算机上,而不向用户询问保存位置。)
Content-Disposition就是当用户想把请求所得的内容存为一个文件的时候提供一个默认的文件名。具体的定义如下
content-disposition = “Content-Disposition” “:”
disposition-type *( “;” disposition-parm )
disposition-type = “attachment” | disp-extension-token
disposition-parm = filename-parm | disp-extension-parm
filename-parm = “filename” “=” quoted-string
disp-extension-token = token
disp-extension-parm = token “=” ( token | quoted-string )
那么由上可知具体的例子:Content-Disposition: attachment; filename=“filename.xls”,attachment --- 作为附件下载, inline --- 在线打开, 当然filename参数可以包含路径信息,但User-Agnet会忽略掉这些信息,只会把路径信息的最后一部分做为文件名。当你在响应类型为 application/octet- stream情况下使用了这个头信息的话,那就意味着你不想直接显示内容,而是弹出一个”文件下载”的对话框,接下来就是由你来决定“打开”还是“保存” 了。Content-disposition是MIME协议的扩展,由于多方面的安全性考虑没有被标准化,所以可能某些浏览器不支持,比如说IE4.01
我们可以使用程序来使用它,也可以在web服务器(比如IIS)上使用它,只需要在http header上做相应的设置即可 。Communicating Presentation Information in Internet Messages: The Content-Disposition Header 这是一篇关于Content-Disposition的文章().
通过上述,我在goahead-3.1.3中添加 了如下代码(参照过csdn上一位网友后修改的代码):
-
/************* File Down *****************/
-
static bool
-
-
FileDownHandler( Webs *wp )
-
{
-
WebsFileInfo info;
-
char *tmp, *date;
-
ssize nchars;
-
int code;
-
char *pathfile_name; /* Take the path of the file name To find the corresponding file */
-
char *filename_Ext; /* File extension is used to set the MIME type */
-
char *filename; /* The file name Used to save the file name after download */
-
char *disposition; /* Temporary save attachment logo */
-
-
assert( websValid( wp ) );
-
assert( wp->method );
-
assert( wp->filename && wp->filename[0] );
-
pathfilename = websGetVar( wp, "FileName", NULL );
-
-
if ( pathfilename == NULL )
-
return(1);
-
-
filename = sclone( getUrlLastSplit( sclone( pathfilename ), "/" ) );
-
filenameExt = sclone( getUrlLastSplit( sclone( filename ), "." ) );
-
DBG( "filename:%s\n", filename );
-
DBG( "filenameExt:%s\n", filenameExt );
-
-
if ( wp->ext )
-
wfree( wp->ext );
-
-
wp->ext = walloc( 1 + strlen( filenameExt ) + 1 );
-
sprintf( wp->ext, ".%s", sclone( filenameExt ) );
-
free( filenameExt );
-
filenameExt = NULL;
-
if ( wp->filename )
-
wfree( wp->filename ) ;
-
wp->filename = sclone( pathfilename );
-
if ( wp->path )
-
wfree( wp->path );
-
wp->path = sclone( pathfilename );
-
#if !BIT_ROM
-
if ( smatch( wp->method, "DELETE" ) )
-
{
-
if ( unlink( wp->filename ) < 0 )
-
{
-
websError( wp, HTTP_CODE_NOT_FOUND, "Can't delete the URI" );
-
}else {
-
/* No content */
-
websResponse( wp, 204, 0 );
-
}
-
}else if ( smatch( wp->method, "PUT" ) )
-
{
-
/* Code is already set for us by processContent() */
-
websResponse( wp, wp->code, 0 );
-
}else
-
-
#endif /* !BIT_ROM */
-
-
{
-
/*
-
*
-
* If the file is a directory, redirect using the nominated default page
-
*
-
*/
-
if ( websPageIsDirectory( wp ) )
-
{
-
nchars = strlen( wp->path );
-
if ( wp->path[nchars - 1] == '/' || wp->path[nchars - 1] == '\\' )
-
{
-
wp->path[--nchars] = '\0';
-
}
-
tmp = sfmt( "%s/%s", wp->path, websIndex );
-
websRedirect( wp, tmp );
-
wfree( tmp );
-
return(1);
-
}
-
if ( websPageOpen( wp, O_RDONLY | O_BINARY, 0666 ) < 0 )
-
{
-
printf( "\n \033[33m websPageOpen \033[0m \n" );
-
#if BIT_DEBUG
-
-
if ( wp->referrer )
-
{
-
trace( 1, "From %s", wp->referrer );
-
}
-
#endif
-
websError( wp, HTTP_CODE_NOT_FOUND, "Cannot open document for: %s", wp->path );
-
return(1);
-
}
-
DBG( "4" );
-
if ( websPageStat( wp, &info ) < 0 )
-
{
-
websError( wp, HTTP_CODE_NOT_FOUND, "Cannot stat page for URL" );
-
return(1);
-
}
-
DBG( "5" );
-
code = 200;
-
if ( wp->since && info.mtime <= wp->since )
-
{
-
code = 304;
-
}
-
websSetStatus( wp, code );
-
DBG( "6" );
-
websWriteHeaders( wp, info.size, 0 );
-
DBG( "7" );
-
disposition = walloc( 20 + strlen( filename ) + 1 );
-
sprintf( disposition, "attachment;filename=%s", sclone( filename ) );
-
DBG( "%s", disposition );
-
websWriteHeader( wp, "Content-Disposition", sclone( disposition ) );
-
free( filename );
-
free( disposition );
-
filename = NULL;
-
disposition = NULL;
-
if ( (date = websGetDateString( &info ) ) != NULL )
-
{
-
websWriteHeader( wp, "Last-modified", "%s", date );
-
wfree( date );
-
}
-
websWriteEndHeaders( wp );
-
-
/*
-
*
-
* All done if the browser did a HEAD request
-
*
-
*/
-
if ( smatch( wp->method, "HEAD" ) )
-
{
-
websDone( wp );
-
return(1);
-
}
-
websSetBackgroundWriter( wp, fileWriteEvent );
-
}
-
return(1);
-
再结合nginx模块ngx_http_flv_handler的代码我们就可以实现HLS点播了。(暂未完成)
阅读(5044) | 评论(0) | 转发(0) |