ASP .NET Core 导入和导出 Word 文件
本指南探讨了如何导入现有 Word 文档、显示其内容,以及如何使用 IronWord 库从头开始创建文档。 在本教程结束时,您将创建一个 ASP.NET Core Web 应用程序,它可以:
1.上传和阅读 Word 文档 2.在文本框中显示这些文档的内容 3.导出 Docx 文件
本项目非常适合需要将 Word 文档处理集成到其网络应用程序中的开发人员,无论是文档管理系统、报告生成器,还是任何其他涉及 Microsoft Word 文件的场景。
前提条件
要跟上本教程,您必须具备以下条件
- 具备 C# 和 ASP.NET Core 的基本知识
- 已安装 Visual Studio 2019 或更高版本(也可以使用带有 C# 扩展的 Visual Studio Code)
- .NET Core SDK 3.1 或更高版本
如果您不是这些技术方面的专家,也不用担心,我们会指导您完成翻译过程中的每一步!
IronWord是什么?
IronWord 是一个 .NET 库,允许开发人员以编程方式读取、操作和创建 Microsoft Word 文档。 它提供了一个高级 API,可以简化 Word 文件的处理,是我们项目的绝佳选择。
IronWord 的一些主要功能包括
- 阅读和编写各种 Word 格式(DOCX、DOC 等)。
- 处理文档内容和结构
- 文本和段落的格式
- 处理表格、图像和其他文档元素
- 文档的邮件合并流程
- 轻松将 Word 文档转换为 PDF 文档,让您可以将最终的 Word 文档制作成易于共享的 PDF 文件
现在,我们已经对我们要构建的内容和要使用的工具有了一个大致的了解,下面让我们开始设置我们的项目!
2.设置项目
在本节中,我们将创建一个新的 ASP.NET Core 项目,并安装必要的软件包以便与 IronWord 配合使用。
2.1 创建新的 ASP.NET Core 项目
1.打开 Visual Studio 2019 或更高版本。
- 点击"创建新项目"。 3.搜索 "ASP.NET Core Web 应用程序 "并选择。 4.单击 "下一步"。 5.将您的项目命名为 "WordDocumentProcessor"(或任何您喜欢的名称)。 6.为您的项目选择 .NET Framework 和位置,然后单击 "创建"。
2.2 安装 IronWord NuGet 软件包
现在,我们已经建立了项目,让我们添加 IronWord 库:
1.右键单击解决方案资源管理器中的项目。 2.选择 "管理 NuGet 软件包"。 3.在 "浏览 "选项卡中,搜索 "IronWord"。 4.请查找 IronWord 官方软件包。 5.单击 "安装 "将其添加到您的项目中。
2.3 更新现有控制器和视图
让我们更新现有结构,加入文档处理功能:
1.我们将使用 Controllers 文件夹中现有的 HomeController.cs 文件处理逻辑。 2.我们将更新 Views/Home 文件夹中现有的 Index.cshtml 视图,以包含文档上传和显示功能。
现在,我们已经建立了项目并安装了 IronWord 软件包,可以开始实施文档导入和导出功能了。 我们将在 HomeController 中添加新方法,并修改索引视图以处理这些功能。 在下一节中,我们将重点利用现有的控制器和视图结构导入 Word 文档并显示其内容。
3.导入 Word 文档
在本节中,我们将探讨如何在 ASP.NET MVC 应用程序中实现导入和处理 Word 文档的功能。 我们将涵盖用户界面设计和后端控制器逻辑。
3.1 用户界面设计
导入 Word 文档的用户界面设计直观,具有视觉吸引力。 让我们来分析一下用户界面的关键组成部分:
3.1.1 上传区域
上传区域是界面的焦点,邀请用户选择并上传他们的 Word 文档。 结构如下:
<div class="upload-area">
<svg class="file-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
<polyline points="14 2 14 8 20 8"></polyline>
<line x1="16" y1="13" x2="8" y2="13"></line>
<line x1="16" y1="17" x2="8" y2="17"></line>
<polyline points="10 9 9 9 8 9"></polyline>
</svg>
<p>Choose a Word document</p>
<label for="fileInput" class="choose-file">Choose File</label>
<p class="file-info">.DOC or .DOCX (MAX. 10MB)</p>
<button id="uploadBtn" class="upload-button">Upload and Process</button>
</div><div class="upload-area">
<svg class="file-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
<polyline points="14 2 14 8 20 8"></polyline>
<line x1="16" y1="13" x2="8" y2="13"></line>
<line x1="16" y1="17" x2="8" y2="17"></line>
<polyline points="10 9 9 9 8 9"></polyline>
</svg>
<p>Choose a Word document</p>
<label for="fileInput" class="choose-file">Choose File</label>
<p class="file-info">.DOC or .DOCX (MAX. 10MB)</p>
<button id="uploadBtn" class="upload-button">Upload and Process</button>
</div>该代码创建了一个具有视觉吸引力的上传区域,其中包含一个文件图标、一个隐藏的文件输入和一个作为文件选择按钮的样式标签。 翻译还包括可接受的文件类型信息以及启动上传和处理的按钮。
3.1.2 内容显示区域
文件处理完毕后,其内容将显示在一个专用区域:
<div class="content-wrapper">
<h2>Document Content:</h2>
<div id="documentContent" class="content-area">
No content to display.
</div>
</div><div class="content-wrapper">
<h2>Document Content:</h2>
<div id="documentContent" class="content-area">
No content to display.
</div>
</div>本部分提供了一个可滚动区域,用于显示已处理的文档内容。
3.2 控制器实现
HomeController 处理导入和处理 Word 文档的服务器端逻辑。 让我们来看看关键的方法:
3.2.1上传和处理方法
该方法负责处理文件的上传和处理:
[HttpPost]
public IActionResult UploadAndProcess(IFormFile file)
{
if (file == null || file.Length == 0)
{
return Json(new { success = false, message = "No file uploaded." });
}
var fileExtension = Path.GetExtension(file.FileName).ToLowerInvariant();
if (fileExtension != ".doc" && fileExtension != ".docx")
{
return Json(new { success = false, message = "Invalid file type. Please upload a .doc or .docx file." });
}
try
{
var tempFilePath = Path.GetTempFileName();
using (var stream = new FileStream(tempFilePath, FileMode.Create))
{
file.CopyTo(stream);
}
StringBuilder contentBuilder = new StringBuilder();
WordDocument doc = new WordDocument(tempFilePath);
foreach (Paragraph paragraph in doc.Paragraphs)
{
foreach (Text textRun in paragraph.Texts)
{
contentBuilder.AppendLine(textRun.Text);
}
contentBuilder.AppendLine(); // Add an extra line between paragraphs
}
System.IO.File.Delete(tempFilePath); // Clean up the temporary file
return Json(new { success = true, content = FormatContentAsHtml(contentBuilder.ToString()) });
}
catch (Exception ex)
{
_logger.LogError(ex, "Error processing document");
return Json(new { success = false, message = "An error occurred while processing the document." });
}
}[HttpPost]
public IActionResult UploadAndProcess(IFormFile file)
{
if (file == null || file.Length == 0)
{
return Json(new { success = false, message = "No file uploaded." });
}
var fileExtension = Path.GetExtension(file.FileName).ToLowerInvariant();
if (fileExtension != ".doc" && fileExtension != ".docx")
{
return Json(new { success = false, message = "Invalid file type. Please upload a .doc or .docx file." });
}
try
{
var tempFilePath = Path.GetTempFileName();
using (var stream = new FileStream(tempFilePath, FileMode.Create))
{
file.CopyTo(stream);
}
StringBuilder contentBuilder = new StringBuilder();
WordDocument doc = new WordDocument(tempFilePath);
foreach (Paragraph paragraph in doc.Paragraphs)
{
foreach (Text textRun in paragraph.Texts)
{
contentBuilder.AppendLine(textRun.Text);
}
contentBuilder.AppendLine(); // Add an extra line between paragraphs
}
System.IO.File.Delete(tempFilePath); // Clean up the temporary file
return Json(new { success = true, content = FormatContentAsHtml(contentBuilder.ToString()) });
}
catch (Exception ex)
{
_logger.LogError(ex, "Error processing document");
return Json(new { success = false, message = "An error occurred while processing the document." });
}
}本方法可完成以下任务:
1.验证上传的文件,确保文件格式正确(DOC 或 DOCX)。 2.使用 IronWord 库处理文档。 3.以 JSON 格式返回格式化内容。
3.2.2 FormatContentAsHtml 方法
该私人方法将提取的内容格式化为 HTML:
private string FormatContentAsHtml(string content)
{
var lines = content.Split(new[] { Environment.NewLine }, StringSplitOptions.None);
var htmlBuilder = new StringBuilder();
htmlBuilder.Append("<div class='document-content'>");
foreach (var line in lines)
{
if (string.IsNullOrWhiteSpace(line))
{
htmlBuilder.Append("<p> </p>");
}
else
{
htmlBuilder.Append($"<p>{HttpUtility.HtmlEncode(line)}</p>");
}
}
htmlBuilder.Append("</div>");
return htmlBuilder.ToString();
}private string FormatContentAsHtml(string content)
{
var lines = content.Split(new[] { Environment.NewLine }, StringSplitOptions.None);
var htmlBuilder = new StringBuilder();
htmlBuilder.Append("<div class='document-content'>");
foreach (var line in lines)
{
if (string.IsNullOrWhiteSpace(line))
{
htmlBuilder.Append("<p> </p>");
}
else
{
htmlBuilder.Append($"<p>{HttpUtility.HtmlEncode(line)}</p>");
}
}
htmlBuilder.Append("</div>");
return htmlBuilder.ToString();
}这种方法可确保文档内容以 HTML 格式正确排版,每一行都用段落标记包裹,并保留空行。
3.3 客户端 JavaScript
为了处理文件上传和显示处理后的内容,我们使用了 JavaScript:
uploadBtn.addEventListener('click', () => {
const file = fileInput.files[0];
if (!file) {
alert('Please select a file first.');
return;
}
const formData = new FormData();
formData.append('file', file);
uploadBtn.disabled = true;
uploadBtn.textContent = 'Processing...';
documentContent.innerHTML = 'Processing document...';
fetch('/Home/UploadAndProcess', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
if (data.success) {
documentContent.innerHTML = data.content;
} else {
documentContent.innerHTML = `<p>Error: ${data.message}</p>`;
}
})
.catch(error => {
console.error('Error:', error);
documentContent.innerHTML = '<p>An error occurred while processing the document.</p>';
})
.finally(() => {
uploadBtn.disabled = false;
uploadBtn.textContent = 'Upload and Process';
});
});uploadBtn.addEventListener('click', () => {
const file = fileInput.files[0];
if (!file) {
alert('Please select a file first.');
return;
}
const formData = new FormData();
formData.append('file', file);
uploadBtn.disabled = true;
uploadBtn.textContent = 'Processing...';
documentContent.innerHTML = 'Processing document...';
fetch('/Home/UploadAndProcess', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
if (data.success) {
documentContent.innerHTML = data.content;
} else {
documentContent.innerHTML = `<p>Error: ${data.message}</p>`;
}
})
.catch(error => {
console.error('Error:', error);
documentContent.innerHTML = '<p>An error occurred while processing the document.</p>';
})
.finally(() => {
uploadBtn.disabled = false;
uploadBtn.textContent = 'Upload and Process';
});
});JavaScript 代码负责处理文件上传过程,将文件发送到服务器进行处理,并用处理后的内容或错误信息更新用户界面。
3.4 设计用户界面样式
该应用程序使用自定义 CSS 来创建一个有吸引力且用户友好的界面。
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background-color: #f7f7f7;
color: #333;
}
.container {
max-width: 800px;
margin: 0 auto;
padding: 2rem;
padding-top: 0.5rem;
}
h1 {
font-weight: 300;
color: #2c3e50;
text-align: center;
margin-bottom: 1rem;
}
.lead {
text-align: center;
color: #7f8c8d;
margin-bottom: 2rem;
}
.upload-area {
background-color: #ffffff;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
padding: 2rem;
text-align: center;
margin-bottom: 2rem;
transition: all 0.3s ease;
}
.upload-area:hover {
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
}
.file-icon {
width: 64px;
height: 64px;
margin-bottom: 1rem;
color: #3498db;
}
.choose-file {
background-color: #ecf0f1;
color: #2c3e50;
border: none;
padding: 0.5rem 1rem;
border-radius: 4px;
cursor: pointer;
transition: background-color 0.3s ease;
}
.choose-file:hover {
background-color: #d5dbdb;
}
.file-info {
font-size: 0.9em;
color: #95a5a6;
margin-top: 0.5rem;
}
.upload-button {
background-color: #3498db;
color: white;
border: none;
padding: 0.75rem 1.5rem;
border-radius: 4px;
cursor: pointer;
transition: background-color 0.3s ease;
margin-top: 1rem;
}
.upload-button:hover {
background-color: #2980b9;
}
.content-wrapper {
background-color: #ffffff;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
padding: 1rem;
margin-top: 2rem;
}
.content-area {
max-height: 300px;
overflow-y: auto;
padding: 1rem;
background-color: #f9f9f9;
border-radius: 4px;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
font-size: 14px;
line-height: 1.6;
}
.content-area::-webkit-scrollbar {
width: 8px;
}
.content-area::-webkit-scrollbar-track {
background: #f1f1f1;
border-radius: 4px;
}
.content-area::-webkit-scrollbar-thumb {
background: #bdc3c7;
border-radius: 4px;
}
.content-area::-webkit-scrollbar-thumb:hover {
background: #95a5a6;
}
.document-content p {
margin: 0 0 10px 0;
}
</style>该 CSS 采用浅色配色方案,营造出简洁、现代的外观。 上传区域采用带有微妙阴影效果的白色背景,而内容区域则采用带有浅灰色背景的可滚动设计。 使用 border-radius 和 box-shadow 属性可以增加界面元素的深度和视觉趣味性。
4.导出 Word 文档
在继续增强 Word 文档处理器的同时,让我们添加导出文档的功能。 该功能将允许用户从我们的应用程序中生成新的 Word 文档。
4.1 更新用户界面
首先,我们将在导航栏中添加 "导出 "选项。 打开 Views/Shared 文件夹中的 _Layout.cshtml 文件,找到 元素。 让我们为导出功能添加一个新的列表项:
<li class="nav-item">
<a class="nav-link" id="exportLink" href="#" onclick="exportDocument(); return false;"><i class="fas fa-file-export"></i> Export</a>
</li><li class="nav-item">
<a class="nav-link" id="exportLink" href="#" onclick="exportDocument(); return false;"><i class="fas fa-file-export"></i> Export</a>
</li>我们将使用 Font Awesome 制作图标,因此请确保在
部分有 CSS 链接。 该代码在导航栏中添加了一个 "导出 "链接。 图标使用了 Font Awesome,点击后会调用 exportDocument() 函数。 href="#"和返回 false 将阻止默认链接行为。4.2 实现客户端导出逻辑
现在,让我们添加处理导出过程的 JavaScript 函数。 在_Layout.cshtml文件的底部,也就是结尾的










