From: David H. <dav...@gm...> - 2011-01-31 19:49:38
|
On Mon, Jan 31, 2011 at 12:09 PM, Nelson, Erik - 2 < eri...@ba...> wrote: > > Dean Michael Berris wrote on Saturday, January 29, 2011 8:33 AM > > On Sat, Jan 29, 2011 at 7:08 AM, David Hite <dav...@gm...> wrote: > >> However, now I have the problem that response.content is a string. > >> How do I > >> send binary data, such as an image file? > >> > > > > The way I would do it is to somehow mmap the file, get the mmap'ed > > pointer, and copy the data into response.content directly. Binary data > > is held fine by std::string instances, you just have to reserve the > > appropriate amount of memory when you're doing that. > > > > This question will continue to come up. It's true that std::string *can* > hold binary data. It's just not *natural*. The std::string interface is > strongly influenced by null-terminated strings. Things that the interface > implies (like string.c_str() or string(char*) constructor actually do what > you'd think) are broken if you use std::string with binary data. > > The more natural interface (used by asio as well) is a buffer object which > is just a tuple of the form {void*, size_t}, which is easily constructed > from a string, vector<char>, array, or just about any container that the > user has for the data. The user should *not* be forced to make a copy of > their data in a std::string just to satisfy the network library. > > Erik > > > _______________________________________________ > Cpp-netlib-devel mailing list > Cpp...@li... > https://lists.sourceforge.net/lists/listinfo/cpp-netlib-devel > Hey Erik, Good point! I agree. vector<char> seems to be a good standard. In fact, it looks like vector<char> is (or will be) the mandated underlying storage container for std::string. For info, here's what I have working. It seems the easy pitfall is using assignment operator "=" with a char* buffer for a string assumes NULL terminated string. The alternative is to use the string constructor with a char* and size. Here's the code to load binary files (i.e. images) and serve with synchronous server. namespace http = boost::network::http; namespace utils = boost::network::utils; namespace fs = boost::filesystem; void serveFile(const Server::request &request, Server::response &response){ // get destination request for image file Server::string_type dest = destination(request); // internal document root string doc_root_path = "/path/to/doc_root" // set boost::filesystem::path (using filesystem "/" operator for directory/path concatenation fs::path file(doc_root_path / dest); // optional... perform error detection on existence of file... ifstream infile(file.c_str()); int size = fs::file_size(file); char *buf = new char[size]; infile.read(buf, size); // copy binary file into string string bin_str(buf, read_count); // set response contents response.content = bin_str; // set status response.status = Server::response::ok; // optional... check for file extension and assign mime type accordingly... // string file_ext = file.extension().c_str(); // Generic mime type for image (binary) file types http::request_header<http::tags::http_server> content_type = {"Content-Type", "x-application/octet-stream"}; response.headers.push_back( content_type ); } -Dave- |