|
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-
|