boost: Uncompress http response using gzip failed - c++

I'm trying to uncompress http body response using boost gzip filters. I'm using the standard code example provided everywhere:
std::string source = "c:\\install\\data.gz";
std::string destination = "c:\\install\\data.txt";
using namespace std;
using namespace boost::iostreams;
ifstream file(source, ios_base::in | ios_base::binary);
filtering_streambuf<input> in;
in.push(gzip_decompressor());
in.push(file);
ofstream unzipped(destination, std::ios::out | std::ios::binary);
boost::iostreams::copy(in, unzipped);
In this scenario, I saved content of the page into source file before. The problem is that this code doesn't work with some sites using gzip-encoding (for example, http://mail.ru - the biggest russian portal). Other sites, for example, http://bing.com is uncompressed perfectly.
I wrote small code to test saved data using GZipStream. It work fine even with mail.ru:
String source = #"c:\install\data.gz";
String destination = #"c:\install\data.txt";
using (FileStream inFile = new FileStream(source, FileMode.Open))
{
using (FileStream outFile = File.Create(destination))
{
using (GZipStream Decompress = new GZipStream(inFile, CompressionMode.Decompress))
{
Decompress.CopyTo(outFile);
}
}
}
Can anybody explain what's wrong with me, mail.ru or gzip?

Related

Unable to write json data to file in c++

I have a json data which I want to write to a json file in c++. I am using nlohmann json and below is the code:
using nlohmann::json;
std::ofstream output_file("C:\\Program Files (x86)\\output.json");
json outJson;
std::time_t now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
std::string created(30, '\0');
std::strftime(&created[0], created.size(), "%Y-%m-%d %H:%M:%S", std::localtime(&now));
outJson["Created"] = created;
outJson["DataId"] = "T-452";
outJson["Type"] = "UserData";
output_file << outJson;
But nothing is getting saved in output.json.
Explicit serialisation and calling close() before exiting should do the trick here.
output_file << outJson.dump(4);
output_file.close();

Serialize PNG and Send to Rest Client

iam sending images in the png format to my rest clients.
But when i download the file on the client side and try to open it, i will get errors.
I believe the Headers of the file are missing, but how can i add them to the serverresponse?
On the details of my picture i can see, that the size and so on is missing.
ifstream Stream;
Stream.open(FullFileName,std::ios::binary);
string Content, Line;
if (Stream)
{
while (getline(Stream,Line)){
Content += Line;
}
}
Stream.close();
Request::request->set_body(Content);
After searching around found a post post on this side.
And the Sequenze i create from that.
ifstream *Stream = new ifstream(FullFileName, std::ios::in | std::ios::binary);
std::ostringstream *oss = new ostringstream();
*oss << Stream->rdbuf();
string *Content = new string(oss->str());
Stream->close();
Request::request->set_body(*Content);

How to save poco uploaded file

I want to upload file using poco library.
Now I have the uploaded file in the istream variable but I don't know how I can save it to a file?
Here is my code where i can get the length of the file.
void handlePart(const MessageHeader &header, std::istream &stream) {
_type = header.get("Content-Type", "(unspecified)");
if (header.has("Content-Disposition")) {
std::string disp;
NameValueCollection params;
MessageHeader::splitParameters(header["Content-Disposition"], disp, params);
_name = params.get("name", "(unnamed)");
_fileName = params.get("filename", "(unnamed)");
}
CountingInputStream istr(stream);
NullOutputStream ostr;
StreamCopier::copyStream(istr, ostr);
_length = istr.chars();
}
Also now it's 1 file uploaded in the form if there be more than 1 file how it will be managed in istream?
Now there is 2 days I'm searching and testing different ways but I couldn't find any way, please help to resolve this problem.
Thank you in advanced.
Depend on #Abhinav question on this post:
We can write save code like this:
if (fileName.length() != 0){
std::ofstream fout( fileName, std::ios::binary);
fileList.push_back(fileName);
fout << stream.rdbuf() ;
fout.close();
}
But unfortunately it's working for one file if there is more than one this code can't catch correctly.

How to decompress gzipstream with zlib

Can someone tell me which function I need to use in order to decompress a byte array that has been compressed with vb.net's gzipstream. I would like to use zlib.
I've included the zlib.h but I haven't been able to figure out what function(s) I should use.
You can take a look at The Boost Iostreams Library:
#include <fstream>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/filter/gzip.hpp>
std::ifstream file;
file.exceptions(std::ios::failbit | std::ios::badbit);
file.open(filename, std::ios_base::in | std::ios_base::binary);
boost::iostreams::filtering_stream<boost::iostreams::input> decompressor;
decompressor.push(boost::iostreams::gzip_decompressor());
decompressor.push(file);
And then to decompress line by line:
for(std::string line; getline(decompressor, line);) {
// decompressed a line
}
Or entire file into an array:
std::vector<char> data(
std::istreambuf_iterator<char>(decompressor)
, std::istreambuf_iterator<char>()
);
You need to use inflateInit2() to request gzip decoding. Read the documentation in zlib.h.
There is a lot of sample code in the zlib distribution. Also take a look at this heavily documented example of zlib usage. You can modify that one to use inflateInit2() instead of inflateInit().
Here is a C function that does the job with zlib:
int gzip_inflate(char *compr, int comprLen, char *uncompr, int uncomprLen)
{
int err;
z_stream d_stream; /* decompression stream */
d_stream.zalloc = (alloc_func)0;
d_stream.zfree = (free_func)0;
d_stream.opaque = (voidpf)0;
d_stream.next_in = (unsigned char *)compr;
d_stream.avail_in = comprLen;
d_stream.next_out = (unsigned char *)uncompr;
d_stream.avail_out = uncomprLen;
err = inflateInit2(&d_stream, 16+MAX_WBITS);
if (err != Z_OK) return err;
while (err != Z_STREAM_END) err = inflate(&d_stream, Z_NO_FLUSH);
err = inflateEnd(&d_stream);
return err;
}
The uncompressed string is returned in uncompr. It's a null-terminated C string so you can do puts(uncompr). The function above only works if the output is text. I have tested it and it works.
Have a look at the zlib usage example. http://www.zlib.net/zpipe.c
The function that does the real work is inflate(), but you need inflateInit() etc.

Unable to capture standard output of process using Boost.Process

Currently am using Boost.Process from the Boost sandbox, and am having issues getting it to capture my standard output properly; wondering if someone can give me a second pair of eyeballs into what I might be doing wrong.
I'm trying to take thumbnails out of RAW camera images using DCRAW (latest version), and capture them for conversion to QT QImage's.
The process launch function:
namespace bf = ::boost::filesystem;
namespace bp = ::boost::process;
QImage DCRawInterface::convertRawImage(string path) {
// commandline: dcraw -e -c <srcfile> -> piped to stdout.
if ( bf::exists( path ) ) {
std::string exec = "bin\\dcraw.exe";
std::vector<std::string> args;
args.push_back("-v");
args.push_back("-c");
args.push_back("-e");
args.push_back(path);
bp::context ctx;
ctx.stdout_behavior = bp::capture_stream();
bp::child c = bp::launch(exec, args, ctx);
bp::pistream &is = c.get_stdout();
ofstream output("C:\\temp\\testcfk.jpg");
streamcopy(is, output);
}
return (NULL);
}
inline void streamcopy(std::istream& input, std::ostream& out) {
char buffer[4096];
int i = 0;
while (!input.eof() ) {
memset(buffer, 0, sizeof(buffer));
int bytes = input.readsome(buffer, sizeof buffer);
out.write(buffer, bytes);
i++;
}
}
Invoking the converter:
DCRawInterface DcRaw;
DcRaw.convertRawImage("test/CFK_2439.NEF");
The goal is to simply verify that I can copy the input stream to an output file.
Currently, if I comment out the following line:
args.push_back("-c");
then the thumbnail is written by DCRAW to the source directory with a name of CFK_2439.thumb.jpg, which proves to me that the process is getting invoked with the right arguments. What's not happening is connecting to the output pipe properly.
FWIW: I'm performing this test on Windows XP under Eclipse 3.5/Latest MingW (GCC 4.4).
[UPDATE]
From debugging, it would appear that by the time the code reaches streamcopy, the file/pipe is already closed - bytes = input.readsome(...) is never any value other than 0.
Well I think that you need to redirect correctly the output stream. In my application something like this works :
[...]
bp::command_line cl(_commandLine);
bp::launcher l;
l.set_stdout_behavior(bp::redirect_stream);
l.set_stdin_behavior(bp::redirect_stream);
l.set_merge_out_err(true);
bp::child c = l.start(cl);
bp::pistream& is = c.get_stdout();
string result;
string line;
while (std::getline(is, line) && !_isStopped)
{
result += line;
}
c.wait();
[...]
Without the redirect the stdout will go nowhere if I remember correctly. It is a good practice to wait for the process end if you want to get the whole output.
EDIT:
I'm on Linux with perhaps an old version of boost.process. i realize that your code is similar to the snippet I gave you. The c.wait() might be the key ...
EDIT: Boost.process 0.1 :-)
If migrating to the "latest" boost.process isn't an issue (as you sure know, there are several variants for this library) ,you could use the following (http://www.highscore.de/boost/process0.5/)
file_descriptor_sink sink("stdout.txt");
execute(
run_exe("test.exe"),
bind_stdout(sink)
);