#include "stdafx.h" #include "WebsocketServlet_impl.h" WebsocketServlet_impl::WebsocketServlet_impl(acl::redis_client_cluster& cluster, size_t max_conns) { // 创建 session 存储对象 session_ = new acl::redis_session(cluster, max_conns); step_ = 0; } WebsocketServlet_impl::~WebsocketServlet_impl(void) { delete session_; } bool WebsocketServlet_impl::doUnknown(acl::HttpServletRequest&, acl::HttpServletResponse& res) { res.setStatus(400); res.setContentType("text/html; charset="); // 发送 http 响应头 if (res.sendHeader() == false) return false; // 发送 http 响应体 acl::string buf("\r\n"); (void) res.getOutputStream().write(buf); return false; } bool WebsocketServlet_impl::doGet(acl::HttpServletRequest& req, acl::HttpServletResponse& res) { return doPost(req, res); } bool WebsocketServlet_impl::doPost(acl::HttpServletRequest& req, acl::HttpServletResponse& res) { res.setContentType("text/html; charset=utf-8") // 设置响应字符集 .setContentEncoding(false) // 设置是否压缩数据 .setChunkedTransferEncoding(true); // 采用 chunk 传输方式 const char* ip = req.getLocalAddr(); if (ip == NULL || *ip == 0) { logger_error("getLocalAddr error"); return false; } unsigned short port = req.getLocalPort(); if (port == 0) { logger_error("getLocalPort error"); return false; } acl::string local_addr; local_addr << ip << ":" << port; printf("getLocalAddr: %s\r\n", local_addr.c_str()); acl::string html_file; html_file << "www/upload.html"; acl::string buf; if (acl::ifstream::load(html_file, &buf) == false) { logger_error("load %s error %s", html_file.c_str(), acl::last_serror()); return doError(req, res); } buf << ""; // 发送 http 响应体,因为设置了 chunk 传输模式,所以需要多调用一次 // res.write 且两个参数均为 0 以表示 chunk 传输数据结束 return res.write(buf) && res.write(NULL, 0); } bool WebsocketServlet_impl::onPing(unsigned long long, bool) { return sendPong(); } bool WebsocketServlet_impl::onPong(unsigned long long, bool) { return sendPing(); } bool WebsocketServlet_impl::onMessage(unsigned long long payload_len, bool text, bool finish) { (void) text; (void) finish; switch (step_) { case 0: step_++; return getFilename(payload_len); case 1: step_++; if (getFilesize(payload_len) == false) { fp_.close(); return false; } return true; case 2: if (saveFile(payload_len) == false) { fp_.close(); return false; } return true; default: return true; } } bool WebsocketServlet_impl::getFilename(unsigned long long payload_len) { if (readData(payload_len, filename_) == false) { printf("read filename error\r\n"); return false; } printf("get filename=%s\r\n", filename_.c_str()); if (fp_.open_trunc(filename_) == false) { printf("open %s error %s\r\n", filename_.c_str(), acl::last_serror()); return false; } return true; } bool WebsocketServlet_impl::getFilesize(unsigned long long payload_len) { acl::string buf; if (readData(payload_len, buf) == false) { printf("read filesize error\r\n"); fp_.close(); return false; } filesize_ = atoll(buf.c_str()); nread_ = 0; printf("get filesize=%lld\r\n", filesize_); if (filesize_ <= 0) { fp_.close(); } return filesize_ > 0; } bool WebsocketServlet_impl::readData(unsigned long long len, acl::string& path) { char buf[8192]; while (len > 0) { size_t n = len > sizeof(buf) ? sizeof(buf) : len; int ret = readPayload(buf, n); if (ret == -1) { printf("readPayload error\r\n"); return false; } path.append(buf, ret); len -= ret; } return true; } bool WebsocketServlet_impl::saveFile(unsigned long long len) { char buf[8192]; while (nread_ < filesize_) { size_t left = (size_t) (filesize_ - nread_); size_t n = left > sizeof(buf) ? sizeof(buf) : left; int ret = readPayload(buf, n); if (ret == -1) { printf("readPayload error\r\n"); return false; } if (ret == 0) { break; } nread_ += ret; if (fp_.write(buf, ret) == -1) { printf("write data to %s error %s\r\n", filename_.c_str(), acl::last_serror()); return false; } } printf("file=%s, payload_len=%llu, filesize_=%lld, nread_=%lld\r\n", filename_.c_str(), len, filesize_, nread_); if (nread_ == filesize_) { printf("READ OVER FOR FILE %s\r\n", filename_.c_str()); step_ = 0; filesize_ = 0; nread_ = 0; filename_.clear(); fp_.close(); return sendText("+ok"); } else { return true; } }