我正在尝试将docx文件转换为pdf。我正在使用stackoverflow中的代码,但已修改为允许动态选择要打开的文件(而不是硬编码值)。当我运行它时,我在Open()方法上得到一个例外 - 找不到文件。我使用fileupload控件选择文件,所以我知道文件在那里。发生了什么事?
这是我的代码:
using System;
using System.IO;
using Microsoft.Office.Interop.Word;
using OpenXmlPowerTools;
namespace DocxToPdf
{
public partial class WebForm1 : System.Web.UI.Page
{
public Microsoft.Office.Interop.Word.Document wordDoc;
protected void Page_Load(object sender, EventArgs e)
{
}
protected void UploadButton_Click(object sender, EventArgs e)
{
if (DocxFileUpload.HasFile)
{
string docxFile = DocxFileUpload.PostedFile.FileName;
FileInfo fiFile = new FileInfo(docxFile);
if (Util.IsWordprocessingML(fiFile.Extension))
{
Guid pdfFileGuid = Guid.NewGuid();
string pdfFileLoc = string.Format(@"c:\windows\temp\{0}.pdf", pdfFileGuid.ToString());
Microsoft.Office.Interop.Word.Application appWord = new Microsoft.Office.Interop.Word.Application();
wordDoc = appWord.Documents.Open(docxFile);
wordDoc.ExportAsFixedFormat(pdfFileLoc, WdExportFormat.wdExportFormatPDF);
MsgLabel.Text = "File converted to PDF";
}
else
{
MsgLabel.Text = "Not a WordProcessingML document.";
}
}
else
{
MsgLabel.Text = "You have not specified a file.";
}
}
}
}
“wordDoc = appWord.Documents.Open(docxFile);”上发生错误线。
fileupload控件FileName属性只有文件名,而不是完全限定的路径。我理解为什么我收到“找不到文件”错误 - 这是因为该文件中没有完全限定的路径。我对该小组的问题是,如何获得完全限定的路径和文件名,以便我可以打开它?我运行了一个调试会话并检查了fileupload控件和FileInfo控件的所有属性,但是他们没有。 FileInfo控件的“FullPath”属性设置为“c:\ Program Files(x86)\ IIS Express \ myfile.docx”,但这不是文件所在的位置。
以下是有关错误的更多信息:DocxToPdf.dll中的Exception System.Runtime.InteropServices.COMException(很抱歉,我们找不到您的文件。是否可以移动,重命名或删除?C:\ Windows。 .. \ myfile.docx ...
我已经搜索过这个,但到目前为止还没有运气。请帮忙!感谢。
答案 0 :(得分:1)
首先,您应该知道,对于Web应用程序,有两台计算机正在运行 - 客户端(浏览器运行的位置)和服务器(应用程序所在的位置)。每个都有自己的文件系统。服务器无法访问客户端的文件系统,反之亦然 - 这是出于明显的安全原因。现在也许它适用于开发机器,因为您在本地运行该站点,但它永远不会在生产环境中工作。
因此Microsoft Word无法打开位于客户端计算机上的文件。期。客户端可以上传文件,FileUpload控件将允许您访问字节流 - 但它不会自动在本地保存文件。您也无法访问路径,因为路径位于客户端的文件系统上,并且其文件夹的名称是私人信息。
要使此方案完全正常工作,您需要先使用FileUpload.SaveAs在本地保存上传的文件。然后你应该使用该保存的文件在Word中打开它。像这样:
var filePath = Path.GetTempFileName();
DocxFileUpload.SaveAs(filePath);
var appWord = new Microsoft.Office.Interop.Word.Application();
var wordDoc = appWord.Documents.Open(filePath);
var convertedFilePath = Path.GetTempFileName();
wordDoc.ExportAsFixedFormat(convertedFilePath, WdExportFormat.wdExportFormatPDF);
然后,您需要提供一些方法将转换后的文件恢复到浏览器by writing it to the HTTP response。例如:
Response.Clear();
Response.AddHeader("content-disposition", "attachment; filename=Converted.Pdf");
Response.AddHeader("content-type", "application/pdf");
Response.TransmitFile(convertedFilePath);
不要忘记随后清理文件,否则随着越来越多的用户使用您的应用程序,您将耗尽磁盘空间:
}
finally
{
File.Delete(filePath);
File.Delete(convertedFilePath);
}
我将删除命令放在finally
块中,以便即使出现问题也可以运行,例如请求超时。无论如何,您都需要清理这些文件。您可能还希望安排一个系统任务来每晚清理文件夹,以防其中一个文件由于Word被挂起而被锁定,等等。
另外,请确保您的应用程序的AppPool可以read and write to the temp folder。
如果您想使用单独的处理程序进行下载
如果要在PDF旁边显示其他内容,则必须使用单独的处理程序进行下载。这是一个粗略的大纲:
此解决方案中使用了三个网址:
Upload.aspx
允许用户指定要上传的文件的页面Confirm.asp
响应中显示的页面,其中包含大型iFrame File.ashx
返回iFrame 您已编码Upload.aspx
。
Confirm.aspx
需要代码来接受上传,本地保存,打开Word以及转换文件。转换后的文件的路径需要转换为某种令牌。然后,该页面需要返回包含指向File.ashx?docID=token
的iFrame的页面。
File.ashx
需要设置响应标头,使用标记重新创建PDF文件的路径,并通过HttpResponse返回文件。
在某些时候,你需要弄清楚如何清理临时文件夹,可能是一个定期运行的作业,并删除任何超过10分钟的.doc或.pdf文件,等等。