Modify the newFileResponse method

This commit is contained in:
antao 2019-01-29 10:49:37 +08:00
parent 77c8e8a296
commit 075e3cc6b3
9 changed files with 110 additions and 74 deletions

View File

@ -49,6 +49,6 @@ void Attachment::upload(const HttpRequestPtr &req,
void Attachment::download(const HttpRequestPtr &req,
const std::function<void(const HttpResponsePtr &)> &callback)
{
auto resp = HttpResponse::newFileResponse("./drogon.jpg");
auto resp = HttpResponse::newFileResponse("./drogon.jpg", "", CT_IMAGE_JPG);
callback(resp);
}

View File

@ -111,8 +111,8 @@ int main()
app().registerHttpMethod("/api/v1/handle11/{1}/{2}/?p3={3}&p4={4}", &A::staticHandle);
//lambda example
app().registerHttpMethod("/api/v1/handle2/{1}/{2}", [](const HttpRequestPtr &req, const std::function<void(const HttpResponsePtr &)> &callback, int a, float b) {
LOG_DEBUG << "int a=" << a;
LOG_DEBUG << "float b=" << b;
// LOG_DEBUG << "int a=" << a;
// LOG_DEBUG << "float b=" << b;
HttpViewData data;
data.insert("title", std::string("ApiTest::get"));
std::map<std::string, std::string> para;

View File

@ -449,12 +449,40 @@ void doTest(const HttpClientPtr &client, std::promise<int> &pro)
req = HttpRequest::newHttpRequest();
req->setMethod(drogon::Get);
req->setPath("/drogon.jpg");
client->sendRequest(req, [=](ReqResult result, const HttpResponsePtr &resp) {
client->sendRequest(req, [=, &pro](ReqResult result, const HttpResponsePtr &resp) {
if (result == ReqResult::Ok)
{
if (resp->getBody().length() == 51822)
{
outputGood(req);
auto lastModified = resp->getHeader("last-modified");
//LOG_DEBUG << lastModified;
// Test 'Not Modified'
auto req = HttpRequest::newHttpRequest();
req->setMethod(drogon::Get);
req->setPath("/drogon.jpg");
req->addHeader("If-Modified-Since", lastModified);
client->sendRequest(req, [=, &pro](ReqResult result, const HttpResponsePtr &resp) {
if (result == ReqResult::Ok)
{
if (resp->statusCode() == k304NotModified)
{
outputGood(req);
pro.set_value(1);
}
else
{
LOG_DEBUG << resp->getBody().length();
LOG_ERROR << "Error!";
exit(1);
}
}
else
{
LOG_ERROR << "Error!";
exit(1);
}
});
}
else
{
@ -526,13 +554,12 @@ void doTest(const HttpClientPtr &client, std::promise<int> &pro)
req = HttpRequest::newHttpRequest();
req->setMethod(drogon::Get);
req->setPath("/api/attachment/download");
client->sendRequest(req, [=, &pro](ReqResult result, const HttpResponsePtr &resp) {
client->sendRequest(req, [=](ReqResult result, const HttpResponsePtr &resp) {
if (result == ReqResult::Ok)
{
if (resp->getBody().length() == 51822)
{
outputGood(req);
pro.set_value(1);
}
else
{

View File

@ -73,6 +73,9 @@ class HttpClient : public trantor::NonCopyable
uint16_t port,
bool useSSL = false,
trantor::EventLoop *loop = nullptr);
/// Get the event loop of the client;
virtual trantor::EventLoop *loop() = 0;
/// Use hostString to connect to server
/**

View File

@ -92,7 +92,7 @@ class HttpResponse
static HttpResponsePtr newHttpJsonResponse(const Json::Value &data);
static HttpResponsePtr newHttpViewResponse(const std::string &viewName, const HttpViewData &data = HttpViewData());
static HttpResponsePtr newLocationRedirectResponse(const std::string &path);
static HttpResponsePtr newFileResponse(const std::string &fullPath, const std::string &attachmentFileName = "", bool asAttachment = true);
static HttpResponsePtr newFileResponse(const std::string &fullPath, const std::string &attachmentFileName = "", ContentType type = CT_NONE);
virtual ~HttpResponse() {}
};

View File

@ -70,7 +70,8 @@ enum Version
enum ContentType
{
CT_APPLICATION_JSON = 0,
CT_NONE = 0,
CT_APPLICATION_JSON,
CT_TEXT_PLAIN,
CT_TEXT_HTML,
CT_APPLICATION_X_FORM,

View File

@ -692,7 +692,7 @@ void HttpAppFrameworkImpl::onAsyncRequest(const HttpRequestImplPtr &req, std::fu
callback(cachedResp);
return;
}
auto resp = HttpResponse::newFileResponse(filePath, "", false);
auto resp = HttpResponse::newFileResponse(filePath);
if (!timeStr.empty())
{
resp->addHeader("Last-Modified", timeStr);

View File

@ -28,6 +28,7 @@ class HttpClientImpl : public HttpClient, public std::enable_shared_from_this<Ht
HttpClientImpl(trantor::EventLoop *loop, const std::string &hostString);
virtual void sendRequest(const HttpRequestPtr &req, const HttpReqCallback &callback) override;
virtual void sendRequest(const HttpRequestPtr &req, HttpReqCallback &&callback) override;
virtual trantor::EventLoop *loop() override { return _loop; }
~HttpClientImpl();
private:

View File

@ -68,7 +68,7 @@ HttpResponsePtr HttpResponse::newHttpViewResponse(const std::string &viewName, c
return HttpViewBase::genHttpResponse(viewName, data);
}
HttpResponsePtr HttpResponse::newFileResponse(const std::string &fullPath, const std::string &fileNameForUser, bool asAttachment)
HttpResponsePtr HttpResponse::newFileResponse(const std::string &fullPath, const std::string &attachmentFileName, ContentType type)
{
auto resp = std::make_shared<HttpResponseImpl>();
std::ifstream infile(fullPath, std::ifstream::binary);
@ -79,11 +79,9 @@ HttpResponsePtr HttpResponse::newFileResponse(const std::string &fullPath, const
resp->setCloseConnection(true);
return resp;
}
std::streambuf *pbuf = infile.rdbuf();
std::streamsize filesize = pbuf->pubseekoff(0, infile.end);
pbuf->pubseekoff(0, infile.beg); // rewind
if (HttpAppFrameworkImpl::instance().useSendfile() &&
filesize > 1024 * 200)
//TODO : Is 200k an appropriate value? Or set it to be configurable
@ -98,81 +96,87 @@ HttpResponsePtr HttpResponse::newFileResponse(const std::string &fullPath, const
pbuf->sgetn(&str[0], filesize);
resp->setBody(std::move(str));
}
resp->setStatusCode(k200OK);
std::string filename;
std::string filetype;
if (!fileNameForUser.empty())
if (type == CT_NONE)
{
filename = fileNameForUser;
}
else
{
auto pos = fullPath.rfind("/");
if (pos != std::string::npos)
std::string filename;
if (!attachmentFileName.empty())
{
filename = fullPath.substr(pos + 1);
filename = attachmentFileName;
}
else
{
filename = fullPath;
auto pos = fullPath.rfind("/");
if (pos != std::string::npos)
{
filename = fullPath.substr(pos + 1);
}
else
{
filename = fullPath;
}
}
std::string filetype;
auto pos = filename.rfind(".");
if (pos != std::string::npos)
{
filetype = filename.substr(pos + 1);
transform(filetype.begin(), filetype.end(), filetype.begin(), tolower);
}
if (filetype == "html")
resp->setContentTypeCode(CT_TEXT_HTML);
else if (filetype == "js")
resp->setContentTypeCode(CT_APPLICATION_X_JAVASCRIPT);
else if (filetype == "css")
resp->setContentTypeCode(CT_TEXT_CSS);
else if (filetype == "xml")
resp->setContentTypeCode(CT_TEXT_XML);
else if (filetype == "xsl")
resp->setContentTypeCode(CT_TEXT_XSL);
else if (filetype == "txt")
resp->setContentTypeCode(CT_TEXT_PLAIN);
else if (filetype == "svg")
resp->setContentTypeCode(CT_IMAGE_SVG_XML);
else if (filetype == "ttf")
resp->setContentTypeCode(CT_APPLICATION_X_FONT_TRUETYPE);
else if (filetype == "otf")
resp->setContentTypeCode(CT_APPLICATION_X_FONT_OPENTYPE);
else if (filetype == "woff2")
resp->setContentTypeCode(CT_APPLICATION_FONT_WOFF2);
else if (filetype == "woff")
resp->setContentTypeCode(CT_APPLICATION_FONT_WOFF);
else if (filetype == "eot")
resp->setContentTypeCode(CT_APPLICATION_VND_MS_FONTOBJ);
else if (filetype == "png")
resp->setContentTypeCode(CT_IMAGE_PNG);
else if (filetype == "jpg")
resp->setContentTypeCode(CT_IMAGE_JPG);
else if (filetype == "jpeg")
resp->setContentTypeCode(CT_IMAGE_JPG);
else if (filetype == "gif")
resp->setContentTypeCode(CT_IMAGE_GIF);
else if (filetype == "bmp")
resp->setContentTypeCode(CT_IMAGE_BMP);
else if (filetype == "ico")
resp->setContentTypeCode(CT_IMAGE_XICON);
else if (filetype == "icns")
resp->setContentTypeCode(CT_IMAGE_ICNS);
else
{
resp->setContentTypeCode(CT_APPLICATION_OCTET_STREAM);
}
}
auto pos = filename.rfind(".");
if (pos != std::string::npos)
{
filetype = filename.substr(pos + 1);
transform(filetype.begin(), filetype.end(), filetype.begin(), tolower);
}
bool attachment = (asAttachment || (!fileNameForUser.empty()));
// pick a Content-Type for the file
if (filetype == "html")
resp->setContentTypeCode(CT_TEXT_HTML);
else if (filetype == "js")
resp->setContentTypeCode(CT_APPLICATION_X_JAVASCRIPT);
else if (filetype == "css")
resp->setContentTypeCode(CT_TEXT_CSS);
else if (filetype == "xml")
resp->setContentTypeCode(CT_TEXT_XML);
else if (filetype == "xsl")
resp->setContentTypeCode(CT_TEXT_XSL);
else if (filetype == "txt")
resp->setContentTypeCode(CT_TEXT_PLAIN);
else if (filetype == "svg")
resp->setContentTypeCode(CT_IMAGE_SVG_XML);
else if (filetype == "ttf")
resp->setContentTypeCode(CT_APPLICATION_X_FONT_TRUETYPE);
else if (filetype == "otf")
resp->setContentTypeCode(CT_APPLICATION_X_FONT_OPENTYPE);
else if (filetype == "woff2")
resp->setContentTypeCode(CT_APPLICATION_FONT_WOFF2);
else if (filetype == "woff")
resp->setContentTypeCode(CT_APPLICATION_FONT_WOFF);
else if (filetype == "eot")
resp->setContentTypeCode(CT_APPLICATION_VND_MS_FONTOBJ);
else if (filetype == "png")
resp->setContentTypeCode(CT_IMAGE_PNG);
else if (filetype == "jpg")
resp->setContentTypeCode(CT_IMAGE_JPG);
else if (filetype == "jpeg")
resp->setContentTypeCode(CT_IMAGE_JPG);
else if (filetype == "gif")
resp->setContentTypeCode(CT_IMAGE_GIF);
else if (filetype == "bmp")
resp->setContentTypeCode(CT_IMAGE_BMP);
else if (filetype == "ico")
resp->setContentTypeCode(CT_IMAGE_XICON);
else if (filetype == "icns")
resp->setContentTypeCode(CT_IMAGE_ICNS);
else
{
resp->setContentTypeCode(CT_APPLICATION_OCTET_STREAM);
attachment = true;
resp->setContentTypeCode(type);
}
if (attachment)
if (!attachmentFileName.empty())
{
resp->addHeader("Content-Disposition", "attachment; filename=" + filename);
resp->addHeader("Content-Disposition", "attachment; filename=" + attachmentFileName);
}
return resp;
}