HTML转为pdf,或者转为图片,有个开源工具wkhtmltoX,参照官网主页:https://wkhtmltopdf.org/ 一个好东西。
实际应用:
下载安装,手动命令行 wkhtmltopdf.exe http://www.baidu.com/ c:\.pdf
软件也可以通过调用exe去转换,总感觉多少有点2。
重点来了,好在官方提供dll。看到dll是不是很happy,官方还提供了.h 和.lib是不是更happy。这些就在安装目录下,直接拷贝使用即可。而且目录分配分配很规范bin lib include。
废话少说。只需要一点点耐心,你就可以调用wkhtmltopdf生成pdf,并获取各个回调过程:
/****************************************************
头文件中添加以下代码
****************************************************/
#include
#include
static void pdf_progress_changed(wkhtmltopdf_converter* c, int p); // 类成员函数作为回调函数
static void pdf_phase_changed(wkhtmltopdf_converter* c);
static void pdf_error(wkhtmltopdf_converter* c, const char* msg);
static void pdf_warning(wkhtmltopdf_converter* c, const char* msg);
static void pdf_finish(wkhtmltopdf_converter* c, int p);
static CmyHtmlToPdfDlg* myDlg; // 作为类指针在回调函数中使用类非静态变量和非静态成员函数
/****************************************************
源文件中添加以下代码
****************************************************/
CmyHtmlToPdfDlg::CmyHtmlToPdfDlg(CWnd* pParent /*=NULL*/)
: CDialog(CmyHtmlToPdfDlg::IDD, pParent)
, m_editPipe_data(_T(""))
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
myDlg = this;
}
CmyHtmlToPdfDlg * CmyHtmlToPdfDlg::myDlg = NULL;
void CmyHtmlToPdfDlg::pdf_progress_changed(wkhtmltopdf_converter* c, int p){
printf("%3d%%\r", p);
fflush(stdout);
CString str;
str.Format("pdf progress changed %s",wkhtmltopdf_progress_string(c));
myDlg->m_editPipe.ReplaceSel(str + "\r\n");
}
void CmyHtmlToPdfDlg::pdf_phase_changed(wkhtmltopdf_converter* c){
int phase = wkhtmltopdf_current_phase(c);
printf("pdf phase changed %s\n", wkhtmltopdf_phase_description(c,phase));
CString str;
str.Format("%s", wkhtmltopdf_phase_description(c,phase));
myDlg->m_editPipe.ReplaceSel(str + "\r\n");
}
void CmyHtmlToPdfDlg::pdf_error(wkhtmltopdf_converter* c, const char* msg){
fprintf(stderr, "Error: %s\n", msg);
CString str;
str.Format("pdf error %s", msg);
myDlg->m_editPipe.ReplaceSel(str + "\r\n");
//AfxMessageBox(msg);
}
void CmyHtmlToPdfDlg::pdf_warning(wkhtmltopdf_converter* c, const char* msg){
fprintf(stderr, "Warning: %s\n", msg);
CString str;
str.Format("pdf warning %s", msg);
myDlg->m_editPipe.ReplaceSel(str + "\r\n");
//AfxMessageBox(msg);
}
void CmyHtmlToPdfDlg::pdf_finish(wkhtmltopdf_converter* c, int p) {
printf("%3d%%\r", p);
//fflush(stdout);
int iCode = wkhtmltopdf_http_error_code(c);
int phase = wkhtmltopdf_current_phase(c);
CString str2;
str2.Format("%s", wkhtmltopdf_phase_description(c,phase));
myDlg->m_editPipe.ReplaceSel(str2 + "\r\n");
CString str,str1, tmp;
str.Format("error code %d", iCode);
str1.Format("finish code %d", p);
tmp = str + "\r\n" + str1;
myDlg->m_editPipe.ReplaceSel(tmp + "\r\n");
if (iCode == 0 && p != 0 && str2 == "Done")
{
//MessageBox("下载完成");
if (myDlg == NULL)
{
return;
}
myDlg->mess();
} else
{
;
}
}
void CmyHtmlToPdfDlg::OnBnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
CString strAddress, tmpName;
m_editAddress.GetWindowText(strAddress);
BOOL isOpen = FALSE; //是否打开(否则为保存)
CString defaultDir = "D:\\"; //默认打开的文件路径
CString fileName = "newFile.pdf"; //默认保存的文件名
CString filter = "文件(*.pdf)|*.pdf||"; //文件过虑的类型
CFileDialog openFileDlg(isOpen, defaultDir, fileName, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, filter, NULL);
openFileDlg.GetOFN().lpstrInitialDir = "D:\\my\\"; //默认打开目录
INT_PTR result = openFileDlg.DoModal();
CString filePath = defaultDir + "\\" + fileName;
if(result == IDOK) {
filePath = openFileDlg.GetPathName();
}
CString sWebAddress, strLocaPath;
sWebAddress = strAddress;
strLocaPath = filePath;
std::string tmpPath = strLocaPath;
std::string tmpAddr = sWebAddress;
wkhtmltopdf_global_settings* gs;
wkhtmltopdf_object_settings* os;
wkhtmltopdf_converter* c;
int i = 0;
wkhtmltopdf_init(i);
gs = wkhtmltopdf_create_global_settings();
wkhtmltopdf_set_global_setting(gs, "out", tmpPath.c_str());
os = wkhtmltopdf_create_object_settings();
wkhtmltopdf_set_object_setting(os, "page", tmpAddr.c_str());
c = wkhtmltopdf_create_converter(gs);
wkhtmltopdf_set_progress_changed_callback(c, CmyHtmlToPdfDlg::pdf_progress_changed);
wkhtmltopdf_set_phase_changed_callback(c, CmyHtmlToPdfDlg::pdf_phase_changed);
wkhtmltopdf_set_error_callback(c, CmyHtmlToPdfDlg::pdf_error);
wkhtmltopdf_set_warning_callback(c, CmyHtmlToPdfDlg::pdf_warning);
wkhtmltopdf_set_finished_callback(c, CmyHtmlToPdfDlg::pdf_finish);
wkhtmltopdf_add_object(c, os, NULL);
if( !wkhtmltopdf_convert(c) )
fprintf(stderr, "Convertion failed!");
}
也许看到topdf,想当然认为把pdf改成image就可以转成图片了,然而并不是这样:
wkhtmltoimage_global_settings* gs;
wkhtmltoimage_converter* c;
int i = 0;
wkhtmltoimage_init(i);
gs = wkhtmltoimage_create_global_settings();
wkhtmltoimage_set_global_setting(gs, "out", string_To_UTF8(tmpPath).c_str());
wkhtmltoimage_set_global_setting(gs,"in", string_To_UTF8(tmpAddr).c_str());
c = wkhtmltoimage_create_converter(gs,"");
wkhtmltoimage_set_error_callback(c, CHTMLPrinter::wktox_error);
if( !wkhtmltoimage_convert(c) )
{
fprintf(stderr, "Convertion failed!");
return FALSE;
}
当然大同小异,只是没有这个wkhtmltoimage_object_settings对象而已,我们不可想当然认为有。
具体原因,其他参数怎么用参数是什么,请参照 官网的Library Documentation 网址:https://wkhtmltopdf.org/libwkhtmltox/