最近在做公司的一个内部管理系统,因为自己php不熟,公司又没有asp.net的环境,所以自己最后居然用js+CGI的模式,运行速度倒是飞快了,编码却麻烦的要死……罪过啊,罪过,又不是外网……
废话不多说了,有一个问题就是要在调用我的CGI的时候,返回一个文件下载对话框。
好吧,在网上搜了一下,实际上只是http头里面有这样一段就可以了:
Content-Disposition: attachment; filename= %s\r\n\r\n
找到了php版如下:
$old_name = "E:\a.doc";
$file_name = "新文件名.doc";
if (!file_exists($old_name)) { //检查文件是否存在
echo "文件找不到";
exit;
} else {
$file = fopen($old_name, "r"); // 打开文件
// 输入文件标签
Header("Content-type: application/octet-stream");
Header("Accept-Ranges: bytes");
Header("Accept-Length: ".filesize($old_name));
Header("Content-Disposition: attachment; filename=".$file_name);
// 输出文件内容
echo fread($file, filesize($old_name));
fclose($file);
exit;
}
C#版如下:
public static void ToDownload(string serverfilpath,string filename)
{
FileStream fileStream = new FileStream(serverfilpath, FileMode.Open);
long fileSize = fileStream.Length;
HttpContext.Current.Response.ContentType = "application/octet-stream";
HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment; filename=\"" +UTF_FileName(filename) + "\";");
////attachment — 作为附件下载
////inline — 在线打开
HttpContext.Current.Response.AddHeader("Content-Length", fileSize.ToString());
byte[] fileBuffer = new byte[fileSize];
fileStream.Read(fileBuffer, 0, (int)fileSize);
HttpContext.Current.Response.BinaryWrite(fileBuffer);
fileStream.Close();
HttpContext.Current.Response.End();
}
public static void ToOpen(string serverfilpath, string filename)
{
FileStream fileStream = new FileStream(serverfilpath, FileMode.Open);
long fileSize = fileStream.Length;
HttpContext.Current.Response.ContentType = "application/octet-stream";
HttpContext.Current.Response.AddHeader("Content-Disposition", "inline; filename=\"" + UTF_FileName(filename)+ "\";");
HttpContext.Current.Response.AddHeader("Content-Length", fileSize.ToString());
byte[] fileBuffer = new byte[fileSize];
fileStream.Read(fileBuffer, 0, (int)fileSize);
HttpContext.Current.Response.BinaryWrite(fileBuffer);
fileStream.Close();
HttpContext.Current.Response.End();
}
private static string UTF_FileName(string filename)
{
return HttpUtility.UrlEncode(filename, System.Text.Encoding.UTF8);
}
所以其实最后的C++版也就比较明显了(我没有读本地文件,因为内容直接在一个string的buff里):
printf("Content-type: application/octet-stream\r\n");
printf("Content-Length: %u\r\n",ccpp.filecontent.size());
printf("Content-Disposition: attachment; filename= %s\r\n\r\n",filename.c_str());
const char *ptr = ccpp.filecontent.c_str();
for(unsigned int i =0 ;i < ccpp.filecontent.size();++i)
{
putchar(*(ptr+i));
}
先解释一下,由于webserver会将标准输出重定向,所以用printf实际就是返回到了浏览器端,至于用putchar是因为二进制的原因。
在这里还碰到了一个诡异的问题,即用
write(1,ptr,ccpp.filename.size());
会直接500 error,不知道为什么……
gf on #
赞一个!!
Reply
Biafeffog on #
Nice site <a href="http://google.com" rel="nofollow">....)</a>
Reply
Biafeffog on #
<a href="http://lqzjbbxi.com" rel="nofollow"> :)</a>
Reply