笔记——文档在线阅读的解决方案(未完待续)

  目前现在很多大型的网站或是某些项目需要让用户上传的文档可以在线预览。这个目前我所了解到的有以下几种情况:

    1、pdf 在线阅读

    2、office 在线阅读

  对于pdf目前有很多解决方案了,可以参考 http://www.open-open.com/news/view/1fc3e18  ,对于office在线阅读,目前。我的办法是,先转换为PDF,然后使用pdf在线阅读的方式进行浏览。目前好像很多站点都是这么做的。

  然而,我在项目中,这类文档在线阅读方案是这样的。OFFICE --> PDF  ---> SWF --> PNG 然后用户通过预览图片的方式去查看文档。

这样做的目的就是,可以让尽可能多的平台直接观看文档,因为任何一个平台都能很好的支持PNG图片预览,但这样做,又产生了新的问题。

  1、office 转成PDF 需要用安装office2007 + SaveAsPDFandXPS加载项 亦或是使用office 2010 。后则直接集成了这个加载项。让一个服务器安装一套office 然后功能仅仅用到的是将office转换为pdf。这个代价是比较大的。office还是不便宜的。

  2、pdf 转换为 swf ,好在目前有现成的工具。(不需要UI界面)

  3、swf 转换为 png ,目前也有现场的工具。(不需要UI界面)

  4、因为这一系列过程才能正常的转换一个文档。而这样的工具,最适合的形态是windows 服务。这样不管如何,只要用户上传了文档,我们就可以进行转换。然而,理想是美好的。当我尝试将这个过程变成服务的过程中,遇到了新的问题。windows xp之后,服务是不能直接调用Application(ExE) 的。而将office转换为pdf,其原理是打开文档,使用另存为按钮,将它保存为pdf。而service 不支持图形界面的操作。在此,笔者查尽了资料。最后在CodeProject上找到了答案。原文我就不列举了,因为懒所以没有做笔记的习惯。代码如下:

  1    public class ProcessStarter : IDisposable
  2     {
  3         #region Import Section
  4
  5         private static uint STANDARD_RIGHTS_REQUIRED = 0x000F0000;
  6         private static uint STANDARD_RIGHTS_READ = 0x00020000;
  7         private static uint TOKEN_ASSIGN_PRIMARY = 0x0001;
  8         private static uint TOKEN_DUPLICATE = 0x0002;
  9         private static uint TOKEN_IMPERSONATE = 0x0004;
 10         private static uint TOKEN_QUERY = 0x0008;
 11         private static uint TOKEN_QUERY_SOURCE = 0x0010;
 12         private static uint TOKEN_ADJUST_PRIVILEGES = 0x0020;
 13         private static uint TOKEN_ADJUST_GROUPS = 0x0040;
 14         private static uint TOKEN_ADJUST_DEFAULT = 0x0080;
 15         private static uint TOKEN_ADJUST_SESSIONID = 0x0100;
 16         private static uint TOKEN_READ = (STANDARD_RIGHTS_READ | TOKEN_QUERY);
 17         private static uint TOKEN_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_QUERY_SOURCE | TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_GROUPS | TOKEN_ADJUST_DEFAULT | TOKEN_ADJUST_SESSIONID);
 18
 19         private const uint NORMAL_PRIORITY_CLASS = 0x0020;
 20
 21         private const uint CREATE_UNICODE_ENVIRONMENT = 0x00000400;
 22
 23
 24         private const uint MAX_PATH = 260;
 25
 26         private const uint CREATE_NO_WINDOW = 0x08000000;
 27
 28         private const uint INFINITE = 0xFFFFFFFF;
 29
 30         [StructLayout(LayoutKind.Sequential)]
 31         public struct SECURITY_ATTRIBUTES
 32         {
 33             public int nLength;
 34             public IntPtr lpSecurityDescriptor;
 35             public int bInheritHandle;
 36         }
 37
 38         public enum SECURITY_IMPERSONATION_LEVEL
 39         {
 40             SecurityAnonymous,
 41             SecurityIdentification,
 42             SecurityImpersonation,
 43             SecurityDelegation
 44         }
 45
 46         public enum TOKEN_TYPE
 47         {
 48             TokenPrimary = 1,
 49             TokenImpersonation
 50         }
 51
 52         public enum WTS_CONNECTSTATE_CLASS
 53         {
 54             WTSActive,
 55             WTSConnected,
 56             WTSConnectQuery,
 57             WTSShadow,
 58             WTSDisconnected,
 59             WTSIdle,
 60             WTSListen,
 61             WTSReset,
 62             WTSDown,
 63             WTSInit
 64         }
 65
 66         [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
 67         public struct STARTUPINFO
 68         {
 69             public Int32 cb;
 70             public string lpReserved;
 71             public string lpDesktop;
 72             public string lpTitle;
 73             public Int32 dwX;
 74             public Int32 dwY;
 75             public Int32 dwXSize;
 76             public Int32 dwYSize;
 77             public Int32 dwXCountChars;
 78             public Int32 dwYCountChars;
 79             public Int32 dwFillAttribute;
 80             public Int32 dwFlags;
 81             public Int16 wShowWindow;
 82             public Int16 cbReserved2;
 83             public IntPtr lpReserved2;
 84             public IntPtr hStdInput;
 85             public IntPtr hStdOutput;
 86             public IntPtr hStdError;
 87         }
 88
 89         [StructLayout(LayoutKind.Sequential)]
 90         internal struct PROCESS_INFORMATION
 91         {
 92             public IntPtr hProcess;
 93             public IntPtr hThread;
 94             public int dwProcessId;
 95             public int dwThreadId;
 96         }
 97
 98         [StructLayout(LayoutKind.Sequential)]
 99         private struct WTS_SESSION_INFO
100         {
101             public Int32 SessionID;
102
103             [MarshalAs(UnmanagedType.LPStr)]
104             public String pWinStationName;
105
106             public WTS_CONNECTSTATE_CLASS State;
107         }
108
109         [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
110         static extern uint WTSGetActiveConsoleSessionId();
111
112         [DllImport("wtsapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
113         static extern bool WTSQueryUserToken(int sessionId, out IntPtr tokenHandle);
114
115         [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
116         public extern static bool DuplicateTokenEx(IntPtr existingToken, uint desiredAccess, IntPtr tokenAttributes, SECURITY_IMPERSONATION_LEVEL impersonationLevel, TOKEN_TYPE tokenType, out IntPtr newToken);
117
118         [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
119         static extern bool CreateProcessAsUser(IntPtr token, string applicationName, string commandLine, ref SECURITY_ATTRIBUTES processAttributes, ref SECURITY_ATTRIBUTES threadAttributes, bool inheritHandles, uint creationFlags, IntPtr environment, string currentDirectory, ref STARTUPINFO startupInfo, out PROCESS_INFORMATION processInformation);
120
121         [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
122         static extern bool CloseHandle(IntPtr handle);
123
124         [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
125         static extern int GetLastError();
126
127         [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
128         static extern int WaitForSingleObject(IntPtr token, uint timeInterval);
129
130         [DllImport("wtsapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
131         static extern int WTSEnumerateSessions(System.IntPtr hServer, int Reserved, int Version, ref System.IntPtr ppSessionInfo, ref int pCount);
132
133         [DllImport("userenv.dll", CharSet = CharSet.Auto, SetLastError = true)]
134         static extern bool CreateEnvironmentBlock(out IntPtr lpEnvironment, IntPtr hToken, bool bInherit);
135
136         [DllImport("wtsapi32.dll", ExactSpelling = true, SetLastError = false)]
137         public static extern void WTSFreeMemory(IntPtr memory);
138
139         [DllImport("userenv.dll", SetLastError = true)]
140         [return: MarshalAs(UnmanagedType.Bool)]
141         static extern bool DestroyEnvironmentBlock(IntPtr lpEnvironment);
142
143         #endregion
144
145         public ProcessStarter()
146         {
147
148         }
149
150         public ProcessStarter(string processName, string fullExeName)
151         {
152             processName_ = processName;
153             processPath_ = fullExeName;
154         }
155         public ProcessStarter(string processName, string fullExeName, string arguments)
156         {
157             processName_ = processName;
158             processPath_ = fullExeName;
159             arguments_ = arguments;
160         }
161
162         public static IntPtr GetCurrentUserToken()
163         {
164             IntPtr currentToken = IntPtr.Zero;
165             IntPtr primaryToken = IntPtr.Zero;
166             IntPtr WTS_CURRENT_SERVER_HANDLE = IntPtr.Zero;
167
168             int dwSessionId = 0;
169             IntPtr hUserToken = IntPtr.Zero;
170             IntPtr hTokenDup = IntPtr.Zero;
171
172             IntPtr pSessionInfo = IntPtr.Zero;
173             int dwCount = 0;
174
175             WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, ref pSessionInfo, ref dwCount);
176
177             Int32 dataSize = Marshal.SizeOf(typeof(WTS_SESSION_INFO));
178
179             Int32 current = (int)pSessionInfo;
180             for (int i = 0; i < dwCount; i++)
181             {
182                 WTS_SESSION_INFO si = (WTS_SESSION_INFO)Marshal.PtrToStructure((System.IntPtr)current, typeof(WTS_SESSION_INFO));
183                 if (WTS_CONNECTSTATE_CLASS.WTSActive == si.State)
184                 {
185                     dwSessionId = si.SessionID;
186                     break;
187                 }
188
189                 current += dataSize;
190             }
191
192             WTSFreeMemory(pSessionInfo);
193
194             bool bRet = WTSQueryUserToken(dwSessionId, out currentToken);
195             if (bRet == false)
196             {
197                 return IntPtr.Zero;
198             }
199
200             bRet = DuplicateTokenEx(currentToken, TOKEN_ASSIGN_PRIMARY | TOKEN_ALL_ACCESS, IntPtr.Zero, SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, TOKEN_TYPE.TokenPrimary, out primaryToken);
201             if (bRet == false)
202             {
203                 return IntPtr.Zero;
204             }
205
206             return primaryToken;
207         }
208
209         public void Run()
210         {
211
212             IntPtr primaryToken = GetCurrentUserToken();
213             if (primaryToken == IntPtr.Zero)
214             {
215                 return;
216             }
217             STARTUPINFO StartupInfo = new STARTUPINFO();
218             processInfo_ = new PROCESS_INFORMATION();
219             StartupInfo.cb = Marshal.SizeOf(StartupInfo);
220
221             SECURITY_ATTRIBUTES Security1 = new SECURITY_ATTRIBUTES();
222             SECURITY_ATTRIBUTES Security2 = new SECURITY_ATTRIBUTES();
223
224             string command = "\"" + processPath_ + "\"";
225             if ((arguments_ != null) && (arguments_.Length != 0))
226             {
227                 command += " " + arguments_;
228             }
229
230             IntPtr lpEnvironment = IntPtr.Zero;
231             bool resultEnv = CreateEnvironmentBlock(out lpEnvironment, primaryToken, false);
232             if (resultEnv != true)
233             {
234                 int nError = GetLastError();
235             }
236
237             CreateProcessAsUser(primaryToken, null, command, ref Security1, ref Security2, false, CREATE_NO_WINDOW | NORMAL_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT, lpEnvironment, null, ref StartupInfo, out processInfo_);
238
239             DestroyEnvironmentBlock(lpEnvironment);
240             CloseHandle(primaryToken);
241         }
242
243         public void Stop()
244         {
245             Process[] processes = Process.GetProcesses();
246             foreach (Process current in processes)
247             {
248                 if (current.ProcessName == processName_)
249                 {
250                     current.Kill();
251                 }
252             }
253         }
254
255         public int WaitForExit()
256         {
257             WaitForSingleObject(processInfo_.hProcess, INFINITE);
258             int errorcode = GetLastError();
259             return errorcode;
260         }
261
262         #region IDisposable Members
263
264         public void Dispose()
265         {
266         }
267
268         #endregion
269
270         private string processPath_ = string.Empty;
271         private string processName_ = string.Empty;
272         private string arguments_ = string.Empty;
273         private PROCESS_INFORMATION processInfo_;
274
275         public string ProcessPath
276         {
277             get
278             {
279                 return processPath_;
280             }
281             set
282             {
283                 processPath_ = value;
284             }
285         }
286
287         public string ProcessName
288         {
289             get
290             {
291                 return processName_;
292             }
293             set
294             {
295                 processName_ = value;
296             }
297         }
298
299         public string Arguments
300         {
301             get
302             {
303                 return arguments_;
304             }
305             set
306             {
307                 arguments_ = value;
308             }
309         }
310     }

其调用方式,如下:

1  ProcessStarter  ps = new ProcessStarter(RunProcessName, "Worker.exe");
2                      ps.Run();

第一个参数,是外壳程序,也就是说,当系统登录的时候一定会存在的进程。也就是Login之后,当前用户一定会存在的进程。

第二个参数,是我们需要运行的Application。

这样就可以在windows service中Call到Application了。

到了这里问题好像解决了。但是,我发现服务器必须需要一个用户登录进去,Office 才能转换为PDF。分析了很久的原因。后来突然有一天发现。以为没有Login之前。是没有UI界面的。在没有UI界面之前是不可能打开Office的。所以此路不通!!!

于是乎,继续寻找解决办法。就在昨天,我发现了新的解决办法。但还没有去尝试。如果有人有现场的解决办法,希望能拿出来分享下。

1、Aspose.words.dll 听说这玩意儿可以在不安装OFFICE的情况下将word转换为pdf。目前我没有验证。但,仅仅只能将word转换为pdf还是不够的,我们还有 ppt excel。再者版本问题也是个问题。是否支持 Office 2003 和 Office 2007以上版本。

2、OpenOffice 这个家伙是阿帕奇搞的。听说可以不依靠office的情况下处理这些。但是太大了。我也没来得及去详细的查阅资料。

最后,期待第二篇日志可以解决以上问题。让office文档能在脱离安装office的情况下完美转换。

时间: 09-28

笔记——文档在线阅读的解决方案(未完待续)的相关文章

word文档在线预览解决方案

花了一整天在网上翻关于 “word文档在线预览解决方案” 相关的资料,感觉实现难度比较大还是用PDF来解决好了.. 下面列一下比较好的参考资料吧 参考资料 前端实现在线预览pdf.word.xls.ppt等文件 OFFICE 文档转换为html在线预览 [Asp.net]常见word,excel,ppt,pdf在线预览方案,有图有真相,总有一款适合你! Office文件在线预览功能够折腾的了 Office在线预览及PDF在线预览的实现方式大集合 python3将docx转换成pdf,html文件

WEB文档在线预览解决方案

web页面无法支持预览office文档,但是却可以预览PDF.flash文档,所以大多数解决方案都是在服务端将office文档转换为pdf,然后再通过js的pdf预览插件(谷歌浏览器等已经原生支持嵌入PDF文档)进行查看. Aspose后台转换可以使用Aspose将office文档转换为PDF格式,Aspose功能强大,支持编辑/转换word.excel.ppt.pdf等,且API操作简便快速.Aspose是收费的,你需要下载破解版本. 除了Aspose可以编辑文档,类似的还有NPOI .POI

html内嵌flex同时向flex页面传参实现pdf文档在线阅读

由于项目需求需要实现pdf文档的上传并在线阅读,在网上看了很多关于html在线阅读pdf文档的文章,遇到各种问题,包括不同浏览器之间,同一个浏览器不同版本等问题,最终没有实现.后来就换了一个思路,用flex实现pdf的在线阅读,但是flex不能实现直接阅读pdf(对我而言不行),于是了解到可以通过将pdf转swf之后再实现阅读.下面就来看看实现具体过程: 1,实现pdf转为swf: 2,flex实现swf文件的在线浏览: 3,html内嵌flex实现pdf在线浏览. 1,pdf转swf (1)要

巧用数据流让 Word 文档在线阅读

经常写博客或空间日记的朋友,对网络编辑器(如图1,是CSDN的博客编辑器)并不陌生,也比较容易做出非常绚烂的排版.但这次在做一个BS的项目,客户一直在用Office的软件中的Word来编辑,并没用过这种工具,很陌生,"这里怎么设置行间距?"--让我瞬时摸不到头脑.在原版的系统中,客户发布信息时,索性用屏幕截图工具从Word中截图,然后粘到编辑器中,效果可想而知.后来细想,既然习惯了用Word,何不把Word上传,然后在线预览呢? 图1 查了一下资料,发现并不难,主要就是把Word转成H

flexPaper +swftools实现文档在线阅读

网上已有很多FlexPaper仿百度文库的一些文章,园子里也有很多大牛的详细教程. 结合这次做的例子,在这里详细记录一下使用Flexpaper实现仿百度文库的效果,及自己在跟着园子里的教程做的时候,遇到的一些小问题.希望能给初次接触或者遇到同样问题的同学们提供一些小小的帮助.(描述不足之处,请大家多多见谅,毕竟是第一次在园子里写文章). 1.准备工作:下载FlexPaper及PDF转换工具pdf2swf.exe Flexpaper下载地址:下载 (我下的是1.4.5 Flash Version 

Python学习笔记——基础篇【第二周】未完待续

python介绍 cpython print("alex xx")  c解释器 .pyc(字节码)  机器码 cpu jphthon print("alex xx") java解释器 Java字节码 机器码 cpu irongpython print("alex xx") C#解释器 C#字节码 机器码 cpu ruby js... pypy print("alex xx") 解释器 字节码  机器码 cpu 最快 代码执行的

web文档在线阅览

之前遇到很多各种文档在线阅览的需求,也有不少朋友经常问我这种需求的实现方案,大致试了一下网上的一些比较主流的推荐方案,但都不尽如人意,这里有一个比较全面的总结,需要的朋友可以根据自己的需求到这里查看,Office在线预览及PDF在线预览的实现方式大集合.本文选择功能比较强大,实现比较简单的一种方案,Aspose组件把Office及其PDF文档转换成HTML,然后进行查看. Aspose组件在处理Office及其PDF文档方面非常的强大,据说可以在没有安装Microsoft Office的机器上工

Java实现文档在线预览(openoffice+swfTools+FlexPaper)

      文档在线预览在项目中早就完成了,后来又经过了一次优化.但是一直都没时间去记录遇到的问题,文档在线预览的详细步骤可以参考http://blog.csdn.net/u013614451/article/details/24261503,感谢博主写了这么好的文章帮助我完成了项目中主要的模块.下面是文档转换的工具类DocConvert.java,并标注出我修改的部分. package com.he.util; import java.io.BufferedInputStream; impor

Java模拟实现百度文档在线浏览

Java模拟实现百度文档在线浏览 这个思路是我参考网上而来,代码是我实现. 采用Apache下面的OpenOffice将资源文件转化为pdf文件,然后将pdf文件转化为swf文件,用FlexPaper浏览. ok, A.下载OpenOffice (转换资源文件) B.下载JodConverter(调用OpenOffice) C.下载Swftools(Pdf2Swf) D.下载 FlexPaper(浏览swf文件) 这里我已经全部下载好了,大家只需要下载:http://down.51cto.com