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." });
}
}<HttpPost>
Public Function UploadAndProcess(ByVal file As IFormFile) As IActionResult
If file Is Nothing OrElse file.Length = 0 Then
Return Json(New With {
Key .success = False,
Key .message = "No file uploaded."
})
End If
Dim fileExtension = Path.GetExtension(file.FileName).ToLowerInvariant()
If fileExtension <> ".doc" AndAlso fileExtension <> ".docx" Then
Return Json(New With {
Key .success = False,
Key .message = "Invalid file type. Please upload a .doc or .docx file."
})
End If
Try
Dim tempFilePath = Path.GetTempFileName()
Using stream = New FileStream(tempFilePath, FileMode.Create)
file.CopyTo(stream)
End Using
Dim contentBuilder As New StringBuilder()
Dim doc As New WordDocument(tempFilePath)
For Each paragraph As Paragraph In doc.Paragraphs
For Each textRun As Text In paragraph.Texts
contentBuilder.AppendLine(textRun.Text)
Next textRun
contentBuilder.AppendLine() ' Add an extra line between paragraphs
Next paragraph
System.IO.File.Delete(tempFilePath) ' Clean up the temporary file
Return Json(New With {
Key .success = True,
Key .content = FormatContentAsHtml(contentBuilder.ToString())
})
Catch ex As Exception
_logger.LogError(ex, "Error processing document")
Return Json(New With {
Key .success = False,
Key .message = "An error occurred while processing the document."
})
End Try
End Function本方法可完成以下任务:
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();
}Private Function FormatContentAsHtml(ByVal content As String) As String
Dim lines = content.Split( { Environment.NewLine }, StringSplitOptions.None)
Dim htmlBuilder = New StringBuilder()
htmlBuilder.Append("<div class='document-content'>")
For Each line In lines
If String.IsNullOrWhiteSpace(line) Then
htmlBuilder.Append("<p> </p>")
Else
htmlBuilder.Append($"<p>{HttpUtility.HtmlEncode(line)}</p>")
End If
Next line
htmlBuilder.Append("</div>")
Return htmlBuilder.ToString()
End Function这种方法可确保文档内容以 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文件的底部,也就是结尾的










