在实际环境中测试
在生产中测试无水印。
随时随地为您服务。
本指南探讨了如何导入现有 Word 文档、显示其内容,以及如何使用IronWord 库. 本教程结束时,您将创建一个ASP.NET Core网络应用程序,可以
上传和阅读 Word 文档
在文本框中显示这些文档的内容
导出 Docx 文件
本项目非常适合需要将 Word 文档处理集成到其网络应用程序中的开发人员,无论是文档管理系统、报告生成器,还是任何其他涉及 Microsoft Word 文件的场景。
要跟上本教程,您必须具备以下条件
.NET Core SDK 3.1 或更高版本
如果您不是这些技术方面的专家,也不用担心,我们将指导您完成翻译过程中的每一个步骤!
IronWordMicrosoft Word 是一个 .NET 库,允许开发人员以编程方式读取、处理和创建 Microsoft Word 文档。 它提供了一个高级 API,可以简化 Word 文件的处理,是我们项目的绝佳选择。
IronWord 的一些主要功能包括
轻松将 Word 文档转换为 PDF 文档,让您可以将最终的 Word 文档变成易于共享的 PDF 文件
现在,我们已经对我们要构建的内容和要使用的工具有了一个大致的了解,让我们开始设置我们的项目吧!
在本节中,我们将创建一个新的 ASP.NET Core 项目,并安装必要的软件包以便与 IronWord 配合使用。
打开 Visual Studio 2019 或更高版本。
单击 "创建新项目"。
搜索 "ASP.NET Core Web 应用程序 "并选择。
破损图片 添加自 Pixabay,请从您的文件中选择或将图片拖放到此处。
点击“下一步”。
将您的项目命名为 "WordDocumentProcessor"(文档处理程序(或您喜欢的任何名称).
现在,我们已经建立了项目,让我们添加 IronWord 库:
右键单击解决方案资源管理器中的项目。
选择 "管理 NuGet 软件包"。
在 "浏览 "选项卡中,搜索 "IronWord"。
破损图片 添加自 Pixabay,请从您的文件中选择或将图片拖放到此处。
请查找 IronWord 官方软件包。
让我们更新现有结构,加入文档处理功能:
我们将使用 Controllers 文件夹中现有的 HomeController.cs,用于文档处理逻辑。
我们将更新 "视图/主页 "文件夹中现有的 Index.cshtml 视图,以包含文档上传和显示功能。
现在,我们已经建立了项目并安装了 IronWord 软件包,可以开始实施文档导入和导出功能了。 我们将在 HomeController 中添加新方法,并修改索引视图以处理这些功能。 在下一节中,我们将重点利用现有的控制器和视图结构导入 Word 文档并显示其内容。 我们还可以添加邮件合并功能,但本文将重点介绍导入和导出文档。
在本节中,我们将探讨如何在 ASP.NET MVC 应用程序中实现导入和处理 Word 文档的功能。 我们将涵盖用户界面设计和后端控制器逻辑。
导入 Word 文档的用户界面设计直观,具有视觉吸引力。 让我们来分析一下用户界面的关键组成部分:
上传区域是界面的焦点,邀请用户选择并上传他们的 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>
'INSTANT VB TODO TASK: The following line uses invalid syntax:
'<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="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>
'INSTANT VB TODO TASK: The following line uses invalid syntax:
'<div class="content-wrapper"> <h2> Document Content:</h2> <div id="documentContent" class="content-area"> No content @to display. </div> </div>
本部分提供了一个可滚动区域,用于显示已处理的文档内容。
HomeController 处理导入和处理 Word 文档的服务器端逻辑。 让我们来看看关键的方法:
该方法负责处理文件的上传和处理:
[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 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
本方法可完成以下任务:
验证上传的文件,确保文件格式正确(DOC 或 DOCX)
检查文件扩展名是否正确
使用 IronWord 库处理文档
该私人方法将提取的内容格式化为 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 格式正确排版,每一行都用段落标记包裹,并保留空行。
为了处理文件上传和显示处理后的内容,我们使用了 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';
});
});
uploadBtn.addEventListener( 'click', () =>
If True Then
const file = fileInput.files(0)
If Not file Then
alert( 'Please select a file first.');
Return
End If
const formData = New FormData()
formData.append( 'file', file);
uploadBtn.disabled = True
'INSTANT VB TODO TASK: The following line uses invalid syntax:
' 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 代码负责处理文件上传过程,将文件发送到服务器进行处理,并用处理后的内容或错误信息更新用户界面。
该应用程序使用自定义 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>
<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>
'INSTANT VB TODO TASK: Local functions are not converted by Instant VB:
'(Of style) body
'{
''INSTANT VB TODO TASK: The following line uses invalid syntax:
'' 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 属性可以增加界面元素的深度和视觉趣味性。
在继续增强 Word 文档处理器的同时,让我们添加导出文档的功能。 该功能将允许用户从我们的应用程序中生成新的 Word 文档。
首先,我们将在导航栏中添加 "导出 "选项。 打开 "视图/共享 "文件夹中的_Layout.cshtml文件,并找到_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>
'INSTANT VB TODO TASK: The following line uses invalid syntax:
'<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 制作图标,因此请确保在我们的
部分。 该代码在导航栏中添加了一个 "导出 "链接。 它使用 Font Awesome 作为图标,并调用 exportDocument() 点击时的功能。 href="#"和返回false可以防止默认链接行为。现在,让我们添加处理导出过程的 JavaScript 函数。 At the bottom of our _Layout.cshtml file, just before the closing
tag, we'll add the following script:
<script>
function exportDocument() {
$.ajax({
url: '/Home/ExportWordDocument',
type: 'POST',
success: function (response) {
if (response.success) {
var fileName = prompt("Enter a name for the document (without extension):", "ExportedDocument");
if (fileName === null) {
return;
}
fileName = (fileName.trim()
"ExportedDocument").replace(/\.[^/.]+$/, "") + ".docx";
var a = document.createElement('a');
a.style.display = 'none';
a.href = '/Home/DownloadFile?tempFilePath=' + encodeURIComponent(response.tempFilePath) + '&userFileName=' + encodeURIComponent(fileName);
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
} else {
alert('Failed to export document: ' + response.message);
}
},
error: function () {
alert('An error occurred while exporting the document.');
}
});
}
</script>
<script>
function exportDocument() {
$.ajax({
url: '/Home/ExportWordDocument',
type: 'POST',
success: function (response) {
if (response.success) {
var fileName = prompt("Enter a name for the document (without extension):", "ExportedDocument");
if (fileName === null) {
return;
}
fileName = (fileName.trim()
"ExportedDocument").replace(/\.[^/.]+$/, "") + ".docx";
var a = document.createElement('a');
a.style.display = 'none';
a.href = '/Home/DownloadFile?tempFilePath=' + encodeURIComponent(response.tempFilePath) + '&userFileName=' + encodeURIComponent(fileName);
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
} else {
alert('Failed to export document: ' + response.message);
}
},
error: function () {
alert('An error occurred while exporting the document.');
}
});
}
</script>
Private Function exportDocument() As [function](Of script)
$.ajax({ url: '/Home/ExportWordDocument', type: 'POST', success: @function(response) { if(response.success) { var fileName = prompt("Enter a name for the document (without extension):", "ExportedDocument"); if(fileName === Nothing) { Return; } fileName = (fileName.trim() "ExportedDocument").replace(/\.[^/.]+$/, "") + ".docx"; var a = document.createElement("a"c); a.style.display = 'none'; a.href = '/Home/System.Nullable<DownloadFile>tempFilePath=' + encodeURIComponent(response.tempFilePath) + '&userFileName=' + encodeURIComponent(fileName); document.body.appendChild(a); a.click(); document.body.removeChild(a); } else { alert('Failed @to export document: ' + response.message); } }, @error: @function() { alert('An @error occurred while exporting the document.'); } });
End Function
'INSTANT VB TODO TASK: The following line uses invalid syntax:
'</script>
此 JavaScript 函数向服务器发送 AJAX POST 请求,以创建 Word 文档。 成功后,它会提示用户输入文件名,然后创建一个临时链接来下载文件。该链接会被自动点击,然后从 DOM 中删除。 如果在任何阶段出现错误,都会向用户发出警告。
现在,让我们来实现服务器端逻辑。 打开 Controllers 文件夹中的 HomeController.cs 文件。 我们将添加两种新方法来处理导出过程。
首先,让我们添加创建 Word 文档的方法:
[HttpPost]
public IActionResult ExportWordDocument()
{
try
{
WordDocument doc = new WordDocument();
doc.AddText("Test Word");
string tempFileName = $"TempDoc_{Guid.NewGuid()}.docx";
string tempFilePath = Path.Combine(_environment.WebRootPath, "TempFiles", tempFileName);
Directory.CreateDirectory(Path.GetDirectoryName(tempFilePath));
doc.SaveAs(tempFilePath);
return Json(new { success = true, tempFilePath = $"/TempFiles/{tempFileName}" });
}
catch (Exception ex)
{
_logger.LogError(ex, "Error exporting Word document");
return Json(new { success = false, message = "An error occurred while exporting the document." });
}
}
[HttpPost]
public IActionResult ExportWordDocument()
{
try
{
WordDocument doc = new WordDocument();
doc.AddText("Test Word");
string tempFileName = $"TempDoc_{Guid.NewGuid()}.docx";
string tempFilePath = Path.Combine(_environment.WebRootPath, "TempFiles", tempFileName);
Directory.CreateDirectory(Path.GetDirectoryName(tempFilePath));
doc.SaveAs(tempFilePath);
return Json(new { success = true, tempFilePath = $"/TempFiles/{tempFileName}" });
}
catch (Exception ex)
{
_logger.LogError(ex, "Error exporting Word document");
return Json(new { success = false, message = "An error occurred while exporting the document." });
}
}
<HttpPost>
Public Function ExportWordDocument() As IActionResult
Try
Dim doc As New WordDocument()
doc.AddText("Test Word")
Dim tempFileName As String = $"TempDoc_{Guid.NewGuid()}.docx"
Dim tempFilePath As String = Path.Combine(_environment.WebRootPath, "TempFiles", tempFileName)
Directory.CreateDirectory(Path.GetDirectoryName(tempFilePath))
doc.SaveAs(tempFilePath)
Return Json(New With {
Key .success = True,
Key .tempFilePath = $"/TempFiles/{tempFileName}"
})
Catch ex As Exception
_logger.LogError(ex, "Error exporting Word document")
Return Json(New With {
Key .success = False,
Key .message = "An error occurred while exporting the document."
})
End Try
End Function
此方法使用 IronWord 库创建一个新的 Word 文档,添加一些测试文本,并将其保存到一个具有唯一名称的临时文件中。 它会返回一个 JSON 对象,其中包含成功状态和临时文件的路径。如果出现错误,它会记录异常并返回一条失败消息。
接下来,让我们添加处理文件下载的方法:
[HttpGet]
public IActionResult DownloadFile(string tempFilePath, string userFileName)
{
try
{
string fullPath = Path.Combine(_environment.WebRootPath, tempFilePath.TrimStart('/'));
if (!System.IO.File.Exists(fullPath))
{
return NotFound();
}
byte[] fileBytes = System.IO.File.ReadAllBytes(fullPath);
System.IO.File.Delete(fullPath);
string fileName = !string.IsNullOrEmpty(userFileName) ? userFileName : "ExportedDocument.docx";
return File(fileBytes, "application/vnd.openxmlformats-officedocument.wordprocessingml.document", fileName);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error downloading file");
return BadRequest("An error occurred while downloading the file.");
}
}
[HttpGet]
public IActionResult DownloadFile(string tempFilePath, string userFileName)
{
try
{
string fullPath = Path.Combine(_environment.WebRootPath, tempFilePath.TrimStart('/'));
if (!System.IO.File.Exists(fullPath))
{
return NotFound();
}
byte[] fileBytes = System.IO.File.ReadAllBytes(fullPath);
System.IO.File.Delete(fullPath);
string fileName = !string.IsNullOrEmpty(userFileName) ? userFileName : "ExportedDocument.docx";
return File(fileBytes, "application/vnd.openxmlformats-officedocument.wordprocessingml.document", fileName);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error downloading file");
return BadRequest("An error occurred while downloading the file.");
}
}
<HttpGet>
Public Function DownloadFile(ByVal tempFilePath As String, ByVal userFileName As String) As IActionResult
Try
Dim fullPath As String = Path.Combine(_environment.WebRootPath, tempFilePath.TrimStart("/"c))
If Not System.IO.File.Exists(fullPath) Then
Return NotFound()
End If
Dim fileBytes() As Byte = System.IO.File.ReadAllBytes(fullPath)
System.IO.File.Delete(fullPath)
Dim fileName As String = If(Not String.IsNullOrEmpty(userFileName), userFileName, "ExportedDocument.docx")
Return File(fileBytes, "application/vnd.openxmlformats-officedocument.wordprocessingml.document", fileName)
Catch ex As Exception
_logger.LogError(ex, "Error downloading file")
Return BadRequest("An error occurred while downloading the file.")
End Try
End Function
该方法会检索 ExportWordDocument 创建的临时文件,将其内容读入字节数组,然后删除临时文件。它使用提供的用户文件名,如果没有提供用户文件名,则使用默认文件名。 然后,该方法将文件内容返回为可下载的 Word 文档。 如果找不到文件或出现错误,将返回适当的 HTTP 响应。
为了改善 Word 文档处理器的整体外观和感觉,我们直接在 _Layout.cshtml 文件中添加了自定义 CSS。让我们来看看我们实现的样式:
<style>
:root {
--primary-color: #3498db;
--text-color: #333;
--bg-color: #f8f9fa;
--nav-bg: #fff;
--nav-text: #2c3e50;
--nav-hover: #3498db;
}
body {
font-family: 'Segoe UI', sans-serif;
background-color: var(--bg-color);
color: var(--text-color);
line-height: 1.6;
}
.navbar { background-color: var(--nav-bg); }
.navbar-brand {
font-size: 1.5rem;
font-weight: 700;
color: var(--primary-color);
margin-right: 2rem;
}
.navbar-nav { margin-left: auto; }
.navbar-nav .nav-item { margin-left: 1rem; }
.navbar-nav .nav-link {
color: var(--nav-text);
font-weight: 500;
transition: all 0.3s ease;
padding: 0.5rem 1rem;
border-radius: 4px;
}
.navbar-nav .nav-link:hover, .navbar-nav .nav-link.active {
color: var(--primary-color);
background-color: rgba(52, 152, 219, 0.1);
}
.navbar-nav .nav-link i {
margin-right: 0.5rem;
font-size: 1.1em;
}
.centered-container {
max-width: 800px;
margin: 0 auto;
padding: 2rem;
}
.footer {
background-color: var(--nav-bg);
border-top: 1px solid #ecf0f1;
font-size: 0.9em;
color: var(--nav-text);
}
.footer a {
color: var(--primary-color);
text-decoration: none;
transition: color 0.3s ease;
}
.footer a:hover { color: var(--nav-hover); }
@@media (max-width: 576px) {
.navbar-nav {
margin-left: 0;
margin-top: 1rem;
}
.navbar-nav .nav-item {
margin-left: 0;
margin-bottom: 0.5rem;
}
}
</style>
<style>
:root {
--primary-color: #3498db;
--text-color: #333;
--bg-color: #f8f9fa;
--nav-bg: #fff;
--nav-text: #2c3e50;
--nav-hover: #3498db;
}
body {
font-family: 'Segoe UI', sans-serif;
background-color: var(--bg-color);
color: var(--text-color);
line-height: 1.6;
}
.navbar { background-color: var(--nav-bg); }
.navbar-brand {
font-size: 1.5rem;
font-weight: 700;
color: var(--primary-color);
margin-right: 2rem;
}
.navbar-nav { margin-left: auto; }
.navbar-nav .nav-item { margin-left: 1rem; }
.navbar-nav .nav-link {
color: var(--nav-text);
font-weight: 500;
transition: all 0.3s ease;
padding: 0.5rem 1rem;
border-radius: 4px;
}
.navbar-nav .nav-link:hover, .navbar-nav .nav-link.active {
color: var(--primary-color);
background-color: rgba(52, 152, 219, 0.1);
}
.navbar-nav .nav-link i {
margin-right: 0.5rem;
font-size: 1.1em;
}
.centered-container {
max-width: 800px;
margin: 0 auto;
padding: 2rem;
}
.footer {
background-color: var(--nav-bg);
border-top: 1px solid #ecf0f1;
font-size: 0.9em;
color: var(--nav-text);
}
.footer a {
color: var(--primary-color);
text-decoration: none;
transition: color 0.3s ease;
}
.footer a:hover { color: var(--nav-hover); }
@@media (max-width: 576px) {
.navbar-nav {
margin-left: 0;
margin-top: 1rem;
}
.navbar-nav .nav-item {
margin-left: 0;
margin-bottom: 0.5rem;
}
}
</style>
'INSTANT VB TODO TASK: Local functions are not converted by Instant VB:
'(Of style) :root
'{
' --primary-color: #3498db;
' --text-color: #333;
' --bg-color: #f8f9fa;
' --nav-bg: #fff;
' --nav-text: #2c3e50;
' --nav-hover: #3498db;
' }
body
If True Then
'INSTANT VB TODO TASK: The following line uses invalid syntax:
' font-family: 'Segoe UI', sans-serif; background-color: var(--bg-color); color: var(--text-color); line-height: 1.6; } .navbar { background-color: var(--nav-bg); } .navbar-brand { font-size: 1.5rem; font-weight: 700; color: var(--primary-color); margin-right: 2rem; } .navbar-nav { margin-left: auto; } .navbar-nav.nav-item { margin-left: 1rem; } .navbar-nav.nav-link { color: var(--nav-text); font-weight: 500; transition: all 0.3s ease; padding: 0.5rem 1rem; border-radius: 4px; } .navbar-nav.nav-link:hover, .navbar-nav.nav-link.active { color: var(--primary-color); background-color: rgba(52, 152, 219, 0.1); } .navbar-nav.nav-link i { margin-right: 0.5rem; font-size: 1.1em; } .centered-container { max-width: 800px; margin: 0 auto; padding: 2rem; } .footer { background-color: var(--nav-bg); border-top: 1px solid #ecf0f1; font-size: 0.9em; color: var(--nav-text); } .footer a { color: var(--primary-color); text-decoration: none; transition: color 0.3s ease; } .footer a:hover { color: var(--nav-hover); } @@media(max-width: 576px) { .navbar-nav { margin-left: 0; margin-top: 1rem; } .navbar-nav.nav-item { margin-left: 0; margin-bottom: 0.5rem; } } </style>
该 CSS 块定义了我们应用程序的配色方案和布局。 我们使用 CSS 变量(自定义属性)在整个应用程序中创建一致的色调。样式针对各种元素,包括正文、导航栏和页脚,确保设计的连贯性。 我们为导航栏设计了简洁、现代的外观,具有悬停效果和图标集成功能。 W
虽然我们的应用程序目前侧重于 Word 文档,但我们可以使用IronPDF在翻译过程中,我们还需要考虑到对 PDF 文档的支持,以扩展其功能,涵盖更广泛的文件类型。除了当前的 Word 格式选项外,该系统还可扩展到允许用户以 PDF 文件格式导出文档。
让我们从运行 WordDocumentProcessor 应用程序开始。 如图所示,应用程序已成功加载到浏览器中。 界面简洁、用户友好,顶部的导航栏显示 "主页 "和 "导出 "选项。 主要内容区域显示标题 "Word 文档处理器 "和简要说明:"轻松上传和处理 Word 文档"。
现在,让我们尝试导入一个文档。 在图片中,我们可以看到我们选择了一个名为 "Honey research synopsis.docx "的文件。 文件名将显示在上传区域,取代 "选择文件 "按钮。 我们现在准备上传并处理该文档。
点击 "上传并处理 "后,应用程序将处理文档并显示其内容。 文档内容 "部分现在显示上传文档的开头。 我们可以看到标题 "城市地区的养蜂技术和蜂蜜生产质量 "后面的摘要。 这表明我们的应用程序已成功读取并显示了 Word 文档的内容。
最后,让我们测试一下导出功能。 在图片中,我们可以看到当我们点击导航栏中的 "导出 "按钮时出现的提示。 提示要求我们 "输入文档名称(无扩展名)". 默认名称为 "ExportedDocument",但我们可以根据需要进行更改。 此提示允许我们在下载导出文档之前自定义文档名称。
点击 "确定 "后,应用程序将以指定名称生成一个新的 Word 文档,并启动下载程序。 该导出文档包含我们处理过的内容或我们在应用程序中做过的任何修改。
在整个过程中,我们可以看到应用程序按预期运行。 我们可以使用该应用程序轻松导入 Word 文档、创建文档和导出文档。 用户界面直观且反应灵敏。
总之,我们的 WordDocumentProcessor 应用程序成功地展示了将 Word 文档处理集成到 ASP.NET Core 网络应用程序中的强大功能和灵活性。 通过利用 IronWord 库,我们创建了一个强大的解决方案,可以轻松导入、显示和导出 Word 文档。 该应用程序可作为更复杂的文档管理系统或报告生成器的坚实基础。 对于有兴趣探索 IronWord 功能的开发人员,该库提供了一个免费试用. 试用结束后,授权起价为 $749,这为需要在其网络应用程序中实现高级 Word 文档处理功能的企业提供了一种成本效益高的解决方案。