/
zOMGdev
/
cppcms
Обзор
Документация
Войти
/
zOMGdev
/
cppcms
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
v1.0.5
src/http_file.cpp
207 строк
4 KB
Artyom Beilis
Performance improvements in multipart parsing
20 окт 2014, 19:33
20 окт 2014, 19:33
6c2790b
Код
Авторство
О чём код?
/////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2008-2012 Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com> // // See accompanying file COPYING.TXT file for licensing details. // /////////////////////////////////////////////////////////////////////////////// #define CPPCMS_SOURCE #include <cppcms/http_file.h> #include <cppcms/urandom.h> #include <cppcms/cppcms_error.h> #include <booster/nowide/cstdio.h> #include <booster/nowide/fstream.h> #include <stdlib.h> #include "tohex.h" namespace cppcms { namespace http { struct file::impl_data {}; std::string file::name() const { return name_; } std::string file::mime() const { return mime_; } std::string file::filename() const { return filename_; } long long file::size() { if(saved_in_file_) { std::streampos now=file_.tellp(); file_.seekp(0,std::ios_base::end); long long size = file_.tellp(); file_.seekp(now); return size; } else { return file_data_.tellp(); } } std::istream &file::data() { if(saved_in_file_) return file_; else return file_data_; } std::ostream &file::write_data() { if(saved_in_file_) { return file_; } else { if(size() > static_cast<long long>(size_limit_)) { move_to_file(); return file_; } else { return file_data_; } } } void file::copy_stream(std::istream &in,std::ostream &out) { out << in.rdbuf(); } void file::save_to(std::string const &filename) { if(!saved_in_file_) { file_data_.clear(); file_data_.seekg(0); save_by_copy(filename,file_data_); return; } file_.clear(); file_.seekg(0); file_.sync(); #ifdef CPPCMS_WIN32 file_.close(); /// we can't move opened file on windows as it would be locked if(booster::nowide::rename(tmp_file_name_.c_str(),filename.c_str())!=0) { file_.open(tmp_file_name_.c_str(),std::ios_base::binary | std::ios_base::in | std::ios_base::out); if(!file_) { throw cppcms_error("Failed to reopen file"); } save_by_copy(filename,file_); file_.close(); booster::nowide::remove(tmp_file_name_.c_str()); } #else if(booster::nowide::rename(tmp_file_name_.c_str(),filename.c_str())!=0) { save_by_copy(filename,file_); booster::nowide::remove(tmp_file_name_.c_str()); } file_.close(); #endif removed_ = 1; } void file::save_by_copy(std::string const &file_name,std::istream &in) { booster::nowide::ofstream f(file_name.c_str(),std::ios_base::binary | std::ios_base::out); if(!f) { throw cppcms_error("Failed to save open file:"+file_name); } copy_stream(in,f); f << std::flush; f.close(); } void file::set_memory_limit(size_t size) { size_limit_ = size; } void file::set_temporary_directory(std::string const &d) { temporary_dir_ = d; } void file::move_to_file() { std::string tmp_dir; if(temporary_dir_.empty()) { char const *tmp=getenv("TEMP"); if(!tmp) tmp=getenv("TMP"); if(!tmp) tmp="/tmp"; tmp_dir=tmp; } else { tmp_dir = temporary_dir_; } tmp_file_name_ = tmp_dir + "/cppcms_uploads_"; urandom_device rnd; char buf[16]; char rand[33]={0}; rnd.generate(buf,16); impl::tohex(buf,sizeof(buf),rand); tmp_file_name_.append(rand); tmp_file_name_+=".tmp"; file_.open(tmp_file_name_.c_str(), std::ios_base::binary | std::ios_base::in | std::ios_base::out | std::ios_base::trunc); if(!file_) throw cppcms_error("Failed to create temporary file"); file_data_.seekg(0); copy_stream(file_data_,file_); file_data_.str(""); saved_in_file_ = 1; } file::file() : size_limit_(1024*128), saved_in_file_(0), removed_(0) { } file::~file() { if(saved_in_file_ && !removed_) { file_.close(); if(!tmp_file_name_.empty()) { booster::nowide::remove(tmp_file_name_.c_str()); } } } void file::filename(std::string const &v) { filename_=v; } void file::name(std::string const &v) { name_=v; } void file::mime(std::string const &v) { mime_=v; } } // http } // cppcms