用Visual C++實現SSL下Word檔案發布

來源:互聯網
上載者:User

某網站項目後台管理要求實現一個功能,通過Word檔案上傳的方式實現文檔發布功能。流程如下:使用者選擇一個word文檔,系統自動識別出標題部分,並把餘下的部分轉化為HTML後作為本文發布。

原本的設計思路是把word上傳到後台,由java對文檔進行解析。一番周折後,發現java對word的支援並不理想,而且存在亂碼問題。權衡再三,決定在用戶端使用ActiveX控制項。由控制項實現對word文檔的解析,並自動上傳。 

對word文檔的解析親自做起來才發現困難重重。通過#import或嚮導方式只能實現對某一版本的word文檔的支援。word的版本從word97開始,分別經曆了word2000、wordXP、word2002、word2003、以及當前的word2007。參考了大量的實現方案,發現微軟的autowrap方案最為理想:http://support.microsoft.com/kb/216686/zh-cn。該方案把COM的IDispatch介面進行封裝,通過類比指令碼調用的方式調用COM屬性和方法,而且可以實現預設參數調用,解決我這種問題相當優雅。

這樣,通過_document的saveas方法,就可以把word轉化為html。接下來的問題是,如何打包上傳。第一個問題是如何打包,自然而然的想到zip。由於MFC不提供zip支援,而官方的zlib庫無法實現檔案夾壓縮。以前的一個項目由於找不到解決方案,只能用rar的方式替代,缺點是必須帶上rar的可執行檔。最終在CodeProject上找到一款非常好用的c++源碼,Zip Utils:http://www.codeproject.com/KB/files/zip_utils.aspx。用法非常的簡單,只需要包含一個zip.h即可。建立一個zip檔案只需要以下幾步:

HZIP hZip = CreateZip(m_pszZipPath, NULL);<br />ZipAdd(hZip, sTempFilePath, sTempFileName);<br />……<br />CloseZip(hZip);  

最後一步便是檔案的上傳了。這好辦,網上利用HTTP實現檔案上傳的代碼很多,找來個能用的稍微改改,編譯通過。用php寫了個指令碼,測試正常。

興沖沖的發布。到了測試那裡出現了問題,他用的是tomcat下的FileUpload類,竟然出現異常,而網上關於此異常竟然沒有人給出解決方案。百思不得其解,但HTTP隱藏在平靜的水面下,到底出了什麼問題,只有分析HTTP頭了。

安裝了Fiddler2,編寫了一個Servlet類,開始測試。為了做對比,用HTML的Form寫了個上傳表單,上傳相同的檔案,然後同控制項上傳的HTTP頭進行對比。比較了半天,發現二者除了Agent之類資訊之外,基本相同。都快絕望了,在UltraEdit中一行一行的盯,突然發現,IE產生的HTTP頭在兩個欄位之間多了一個換行。帶著懷疑的態度,我試著加了個換行……點擊運行,竟然通過了。問題找到了,是我改的太狠,把代碼中的應該有的/r/n給一起刪了,原來還以為這是多餘的。原來如此,這就是協議,來不得半點鐘虛假。

於是打包,發布,客戶測試都正常了,代碼也扔一邊去了。突然有一天,在討論系統的安全性時,突然想到,客戶後台都是通過HTTS+USB Key登入的,檔案發布卻是HTTP,這問題有點嚴重。

趕緊找到源碼開始修改,卻發現一下子束手無措,自己對SSL幾乎是一知半解。通過MSDN知道,要實現HTTPS傳輸,只需要在MFC的OpenRequest中傳入INTERNET_FLAG_SECURE參數。心想這麼簡單,代碼一改趕緊測試,卻發現SendRequest調用後直接返回異常:用戶端無效授權。又去查MSDN,終於弄明白原因,寫出以下代碼解決問題: 

CString strServer, strObject;</p><p>DWORD dwServiceType, dwFlags;</p><p>INTERNET_PORT nPort;</p><p>AfxParseURL(serverPath, dwServiceType, strServer, strObject, nPort);</p><p>dwFlags = dwServiceType == AFX_INET_SERVICE_HTTPS ? INTERNET_FLAG_SECURE : 0;</p><p>pHttpConnection = Session.GetHttpConnection(strServer, nPort);</p><p>pHTTP = pHttpConnection->OpenRequest(CHttpConnection::HTTP_VERB_POST, strObject,<br /> NULL, Session.GetContext(), NULL, NULL, dwFlags);</p><p>//發送包頭請求</p><p>pHTTP->AddRequestHeaders(MakeRequestHeaders(strHTTPBoundary));</p><p>bSuccess = FALSE;<br />while (!bSuccess)<br />{<br /> try<br /> {<br /> bSuccess = pHTTP->SendRequestEx(dwTotalRequestLength,<br /> HSR_SYNC | HSR_INITIATE);<br /> }<br /> catch (CInternetException* e)<br /> {<br /> DWORD dwError = e->m_dwError;</p><p>switch (dwError)<br /> {<br /> case ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED:<br /> case ERROR_INTERNET_HTTP_TO_HTTPS_ON_REDIR:<br /> case ERROR_INTERNET_INCORRECT_PASSWORD:<br /> case ERROR_INTERNET_INVALID_CA:<br /> case ERROR_INTERNET_POST_IS_NON_SECURE:<br /> case ERROR_INTERNET_SEC_CERT_CN_INVALID:<br /> case ERROR_INTERNET_SEC_CERT_DATE_INVALID:<br /> // Return ERROR_SUCCESS regardless of clicking on OK or Cancel<br /> if (pHTTP->ErrorDlg(CWnd::FromHandle(GetDesktopWindow()),<br /> dwError,<br /> FLAGS_ERROR_UI_FILTER_FOR_ERRORS<br /> | FLAGS_ERROR_UI_FLAGS_GENERATE_DATA<br /> | FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS,<br /> NULL) != ERROR_SUCCESS)<br /> {<br /> throw e;<br /> }<br /> break;</p><p>default:<br /> throw e;<br /> }</p><p> e->Delete();<br /> }<br />}<br />

問題圓滿解決。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.