acl/app/wizard_demo/httpd_download/http_servlet.cpp

241 lines
6.3 KiB
C++
Raw Normal View History

#include "stdafx.h"
#include "http_servlet.h"
http_servlet::http_servlet(const char* filepath)
{
if (filepath && *filepath)
filepath_ = filepath;
}
http_servlet::~http_servlet(void)
{
}
bool http_servlet::reply(acl::HttpServletRequest& req,
acl::HttpServletResponse& res, int status, const char* fmt, ...)
{
va_list ap;
va_start(ap, fmt);
acl::string buf;
buf.vformat(fmt, ap);
va_end(ap);
bool keep_alive = req.isKeepAlive();
res.setStatus(status)
.setKeepAlive(keep_alive)
.setContentType("text/html; charset=utf-8")
.setContentLength(buf.length());
return res.write(buf) && keep_alive;
}
bool http_servlet::doError(acl::HttpServletRequest& req,
acl::HttpServletResponse& res)
{
acl::string hdr;
req.getClient()->sprint_header(hdr);
logger("error request head:\r\n%s\r\n", hdr.c_str());
(void) reply(req, res, 400, "unknown request method\r\n");
return false;
}
bool http_servlet::doUnknown(acl::HttpServletRequest& req,
acl::HttpServletResponse& res)
{
acl::string hdr;
req.getClient()->sprint_header(hdr);
logger("request head:\r\n%s\r\n", hdr.c_str());
(void) reply(req, res, 400, "unknown request method\r\n");
return false;
}
bool http_servlet::doGet(acl::HttpServletRequest& req,
acl::HttpServletResponse& res)
{
return doPost(req, res);
}
bool http_servlet::doPost(acl::HttpServletRequest& req,
acl::HttpServletResponse& res)
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ http session <20><><EFBFBD>ƣ<EFBFBD><C6A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD>ͣ<EFBFBD><CDA3><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA>֤
// <20><> master_service.cpp <20>ĺ<EFBFBD><C4BA><EFBFBD> thread_on_read <20><><EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD>
// memcached <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/*
const char* sid = req.getSession().getAttribute("sid");
if (*sid == 0)
req.getSession().setAttribute("sid", "xxxxxx");
sid = req.getSession().getAttribute("sid");
*/
// <20><><EFBFBD>ԣ<EFBFBD><D4A3><EFBFBD><EFBFBD>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD><CDB7>¼<EFBFBD><C2BC><EFBFBD><EFBFBD>־<EFBFBD><D6BE>
acl::string hdr;
req.getClient()->sprint_header(hdr);
logger("request head:\r\n%s\r\n", hdr.c_str());
long long int range_from, range_to;
if (req.getRange(range_from, range_to) == false)
return transfer_file(req, res);
else
return transfer_file(req, res, range_from, range_to);
}
// <20><>ͨ<EFBFBD><CDA8><EFBFBD>ع<EFBFBD><D8B9><EFBFBD>
bool http_servlet::transfer_file(acl::HttpServletRequest& req,
acl::HttpServletResponse& res)
{
acl::ifstream in;
// ֻ<><D6BB><EFBFBD><EFBFBD>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD>
if (in.open_read(filepath_) == false)
{
logger_error("open file %s error %s", filepath_.c_str(),
acl::last_serror());
return reply(req, res, 500, "open %s error %s",
filepath_.c_str(), acl::last_serror());
}
long long int fsize = in.fsize();
if (fsize <= 0)
return reply(req, res, 500, "invalid file size: %lld", fsize);
bool keep_alive = req.isKeepAlive();
acl::string hdr_entry;
acl::string filename;
filename.basename(in.file_path()); // <20><><EFBFBD>ļ<EFBFBD>ȫ·<C8AB><C2B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD>ļ<EFBFBD><C4BC><EFBFBD>
hdr_entry.format("attachment;filename=\"%s\"", filename.c_str());
// <20><><EFBFBD><EFBFBD> HTTP <20><>Ӧͷ<D3A6>е<EFBFBD><D0B5>ֶ<EFBFBD>
res.setStatus(200)
.setKeepAlive(keep_alive)
.setContentLength(fsize)
.setContentType("application/octet-stream")
// <20><><EFBFBD><EFBFBD> HTTP ͷ<>е<EFBFBD><D0B5>ļ<EFBFBD><C4BC><EFBFBD>
.setHeader("Content-Disposition", hdr_entry.c_str());
acl::string hdr;
res.getHttpHeader().build_response(hdr);
logger("response head:\r\n%s\r\n", hdr.c_str());
long long n = 0;
char buf[8192];
// <20><><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD>ж<EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD>ݲ<EFBFBD><DDB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݷ<EFBFBD><DDB7><EFBFBD><EFBFBD>ͻ<EFBFBD><CDBB><EFBFBD>
while (!in.eof())
{
int ret = in.read(buf, sizeof(buf), false);
if (ret == -1)
break;
if (res.write(buf, ret) == false)
return false;
n += ret;
//acl_doze(100); // <20><>Ϣ 100 ms <20><><EFBFBD>ڲ<EFBFBD><DAB2><EFBFBD>
}
return n == fsize ? true : false;
}
// ֧<>ֶϵ<D6B6><CFB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݴ<EFBFBD><DDB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
bool http_servlet::transfer_file(acl::HttpServletRequest& req,
acl::HttpServletResponse& res,
long long range_from, long long range_to)
{
if (range_from < 0)
return reply(req, res, 400, "invalid range_from: %lld",
range_from);
if (range_to > 0 && range_to < range_from)
return reply(req, res, 400, "range_from(%lld) > range_to(%lld)",
range_from, range_to);
long long length;
if (range_to >= range_from)
length = range_to - range_from + 1;
else
length = -1;
acl::ifstream in;
// ֻ<><D6BB><EFBFBD><EFBFBD>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD>
if (in.open_read(filepath_) == false)
{
logger_error("open file %s error %s", filepath_.c_str(),
acl::last_serror());
return reply(req, res, 500, "open %s error %s",
filepath_.c_str(), acl::last_serror());
}
long long int fsize = in.fsize();
if (fsize <= 0)
return reply(req, res, 500, "invalid file size: %lld", fsize);
// <20><><EFBFBD><EFBFBD>ƫ<EFBFBD><C6AB>λ<EFBFBD>ó<EFBFBD><C3B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC>ܳ<EFBFBD><DCB3>ȣ<EFBFBD><C8A3>򷵻ش<F2B7B5BB><D8B4><EFBFBD>
if (range_to >= fsize)
return reply(req, res, 400, "range_to(%lld) >= fsize(%lld)",
range_to, fsize);
// <20><><EFBFBD><EFBFBD><EFBFBD>ͻ<EFBFBD><CDBB><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8>ƫ<EFBFBD><C6AB>λ<EFBFBD><CEBB><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>β<EFBFBD><CEB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><DDB3>ȣ<EFBFBD>
// <20><>ֵ<EFBFBD><D6B5>Ϊʵ<CEAA><CAB5>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͻ<EFBFBD><CDBB>˵ij<CBB5><C4B3><EFBFBD>
if (length == -1)
length = fsize - range_from;
// <20><>λ<EFBFBD>ļ<EFBFBD>ƫ<EFBFBD><C6AB>λ<EFBFBD><CEBB>
if (in.fseek(range_from, SEEK_SET) < 0)
return reply(req, res, 500, "fseek(%lld) error %s",
range_from, acl::last_serror());
bool keep_alive = req.isKeepAlive();
acl::string hdr_entry;
acl::string filename;
filename.basename(in.file_path()); // <20><><EFBFBD>ļ<EFBFBD>ȫ·<C8AB><C2B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD>ļ<EFBFBD><C4BC><EFBFBD>
hdr_entry.format("attachment;filename=\"%s\"", filename.c_str());
// <20><><EFBFBD><EFBFBD> HTTP <20><>Ӧͷ<D3A6>е<EFBFBD><D0B5>ֶ<EFBFBD>
res.setStatus(206) // <20><>Ӧ״̬ 206 <20><>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
.setKeepAlive(keep_alive) // <20>Ƿ񱣳ֳ<F1B1A3B3><D6B3><EFBFBD><EFBFBD><EFBFBD>
.setContentLength(length) // ʵ<><CAB5>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><DDB3><EFBFBD>
.setContentType("application/octet-stream") // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD> HTTP ͷ<>е<EFBFBD><D0B5>ļ<EFBFBD><C4BC><EFBFBD>
.setHeader("Content-Disposition", hdr_entry.c_str())
// <20><><EFBFBD>ñ<EFBFBD><C3B1>δ<EFBFBD><CEB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼƫ<CABC><C6AB>λ<EFBFBD>ü<EFBFBD><C3BC><EFBFBD><EFBFBD>ݵ<EFBFBD><DDB5>ܳ<EFBFBD><DCB3><EFBFBD>
.setRange(range_from, range_to > 0
? range_to : fsize - 1, fsize);
// <20><><EFBFBD>ԣ<EFBFBD><D4A3><EFBFBD> HTTP <20><>Ӧͷ<D3A6><CDB7><EFBFBD>ڱ<EFBFBD><DAB1><EFBFBD><EFBFBD><EFBFBD>־<EFBFBD><D6BE>
acl::string hdr;
res.getHttpHeader().build_response(hdr);
logger("response head:\r\n%s\r\n", hdr.c_str());
char buf[8192];
int ret;
size_t size;
// <20><><EFBFBD>ļ<EFBFBD>ָ<EFBFBD><D6B8>λ<EFBFBD>ö<EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD>ݣ<EFBFBD><DDA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݴ<EFBFBD><DDB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͻ<EFBFBD><CDBB><EFBFBD>
while (!in.eof() && length > 0)
{
size = sizeof(buf) > (size_t) length ?
(size_t) length : sizeof(buf);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ false <20><>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD>ζ<EFBFBD><CEB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ش<EFBFBD><D8B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٷ<EFBFBD><D9B7><EFBFBD>
ret = in.read(buf, size, false);
if (ret == -1)
{
printf("read over: %s\r\n", acl::last_serror());
break;
}
if (res.write(buf, ret) == false)
return false;
length -= ret;
//acl_doze(100); // <20><>Ϣ 100 ms <20><><EFBFBD>ڲ<EFBFBD><DAB2><EFBFBD>
}
if (length != 0)
{
logger_error("read file failed");
return false;
}
return true && keep_alive;
2015-07-05 09:44:36 +08:00
}