[Cppcms-users] SOLVED - Re: HTTP response and binary stream (libharu)
Brought to you by:
artyom-beilis
From: augustin <aug...@ov...> - 2015-09-22 04:19:24
|
On Saturday, September 19, 2015 03:22:16 AM Artyom Beilis wrote: > Several points: > (a) You misunderstand meaning of "raw" output - "raw" means you are sending > CGI output including headers etc on your own and CppCMS does not interfere > with it. There only very-very specific cases you may actually need this - > bottom line you don't need it. Ok. I had been struggling with my problem for a few days before I asked, and I was trying to eliminate all possible sources of corruption. I had come to the conclusion that this probably was not it. Thanks for confirming it. > (b) std::ostream is just a character or more > correctly octet stream, std::string is a container that keeps bytes/"C > chars"/octets in it in string friendly way. You can put any binary data to > it. > Now in your case the problem is there app()->response().out() << buf << std::flush; > or cppcms_buf << buf > > Why? std::ostream assumes that buf is NUL terminated string so it would > stop on NUL, and this what corrupts the stream.You need to use > std::ostream::write, i.e. out().write(buf,siz) > That's it > > Artyom Beilis Thank you Artyom! You clearly saw the source of the problem. Joerg also gave me a hint earlier which pointed me in the right direction. I had searched online and found other newbies like me who made the same wrong assumption about the << operator, which, I understand now, should not be used for binary streams. After reading your mail, I still struggled for a while with type casting. I had compile errors such as: error: invalid conversion from 'HPDF_BYTE*' to 'const char*' or: error: invalid static_cast from type 'HPDF_BYTE [4096]' to type 'const char*' Finally, I was forced to use a reinterpret_cast, but apparently it cannot be avoided: // #include <hpdf.h> typedef unsigned char HPDF_BYTE; // my_pdf.cpp: // Create PDF. HPDF_Doc pdf = HPDF_New(pdf::error_handler, NULL); .... .... // Add content to pdf. .... HPDF_SaveToStream (pdf); for (;;) { HPDF_BYTE buf[4096]; HPDF_UINT32 siz = 4096; HPDF_ReadFromStream (pdf, buf, &siz); // cppcms::http::response: app()->response().out().write(reinterpret_cast<const char*>(buf), siz); if (siz == 0) break; } app()->response().out() << std::flush; HPDF_Free(pdf); I am not sure if the << std::flush at the end is necessary, but it doesn't seem to hurt. Artyom, would you like me to create a simple tutorial on using cppcms + libharu on the cppcms wiki? Do you think it may be useful to other people? I can do it if you wish. On Saturday, September 19, 2015 03:26:34 AM Artyom Beilis wrote: > As BTW is shown in this > example: http://libharu.sourceforge.net/how_to_use.html#Save_a_document_to_file_ Yes, I had already seen that page. Actually, the project has moved to github, so I was following the corresponding page there: https://github.com/libharu/libharu/wiki/Usage-examples My main problem is lack of experience (I don't code full time) and I am still baffled by some intricacies of the language and the standard libraries. I often fail to see the relevance of what I am reading to my problem. Once I have solved a problem, it is often frustrating to see that I had actually come across the solution days earlier but failed to understand it! Believe me, I don't take free online help for granted. I always ask as a last resort, when I feel really stuck after having spent a few days trying to fully understand the problem and researching online. As always, I am grateful for you help, and I am in awe of your mastery of the language! :) Blessings, augustin. |