Pruebas en un entorno real
Pruebe en producción sin marcas de agua.
Funciona donde lo necesites.
Esta guía explora cómo importar documentos de Word existentes, mostrar su contenido y crear documentos desde cero utilizando el Biblioteca IronWord. Al final de este tutorial, habrás creado un ASP.NET Coreaplicación web que puede:
Cargar y leer documentos de Word
Mostrar el contenido de estos documentos en un cuadro de texto.
Exportar el archivo Docx
Este proyecto es perfecto para los desarrolladores que necesitan integrar el procesamiento de documentos de Word en sus aplicaciones web, ya sea para sistemas de gestión de documentos, generadores de informes o cualquier otro escenario que involucre archivos de Microsoft Word.
Para seguir este tutorial, deberías tener:
.NET Core SDK 3.1 o posterior
No te preocupes si no eres un experto en estas tecnologías, te guiaremos en cada paso del proceso.!
IronWordes una biblioteca .NET que permite a los desarrolladores leer, manipular y crear documentos de Microsoft Word de forma programática. Ofrece una API de alto nivel que simplifica el trabajo con archivos Word, lo que la convierte en una excelente opción para nuestro proyecto.
Algunas características clave de IronWord incluyen:
Convertir un documento de Word a un documento PDF con facilidad, para que puedas tomar tus documentos finales de Word y convertirlos en archivos PDF fáciles de compartir.
Ahora que tenemos una visión general de lo que estamos construyendo y las herramientas que usaremos, vamos a profundizar en la configuración de nuestro proyecto.!
En esta sección, crearemos un nuevo proyecto de ASP.NET Core e instalaremos los paquetes necesarios para trabajar con IronWord.
Abre Visual Studio 2019 o una versión posterior.
Haga clic en "Crear un nuevo proyecto".
Imagen rota Añadir desde Pixabay, seleccionar desde tus archivos o arrastrar y soltar una imagen aquí.
Haga clic en "Siguiente".
Nombra tu proyecto "WordDocumentProcessor"(o cualquier nombre que prefieras).
Ahora que tenemos nuestro proyecto configurado, agreguemos la biblioteca IronWord:
Haga clic con el botón derecho en su proyecto en el Explorador de soluciones.
Seleccione "Administrar paquetes NuGet".
Imagen rota Añadir desde Pixabay, seleccionar desde tus archivos o arrastrar y soltar una imagen aquí.
Busque el paquete oficial de IronWord.
Actualicemos nuestra estructura existente para incorporar la funcionalidad de procesamiento de documentos:
Utilizaremos el existente HomeController.cs en la carpeta Controllers para nuestra lógica de procesamiento de documentos.
Actualizaremos la vista existente Index.cshtml en la carpeta Views/Home para incluir la funcionalidad de carga y visualización de documentos.
Ahora que tenemos nuestro proyecto configurado y el paquete de IronWord instalado, estamos listos para comenzar a implementar la funcionalidad de importación y exportación de documentos. Añadiremos nuevos métodos a nuestro HomeController y modificaremos la vista Index para manejar estas características. En la siguiente sección, nos centraremos en importar documentos de Word y mostrar su contenido, utilizando nuestra estructura de controlador y vista existente. Podemos añadir la funcionalidad de combinación de correspondencia también, pero nos centraremos en la importación y exportación de documentos en este artículo.
En esta sección, exploraremos cómo implementar una función para importar y procesar documentos Word en una aplicación ASP.NET MVC. Cubriremos tanto el diseño de la interfaz de usuario como la lógica del controlador de back-end.
La interfaz de usuario para importar documentos de Word está diseñada para ser intuitiva y visualmente atractiva. Desglosamos los componentes clave de la interfaz de usuario:
El área de carga es el punto focal de la interfaz, invitando a los usuarios a seleccionar y cargar sus documentos de Word. Aquí está cómo está estructurado:
<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>
Este código crea un área de carga visualmente atractiva con un ícono de archivo, una entrada de archivo oculta y una etiqueta con estilo que actúa como el botón de selección de archivo. También incluye información sobre los tipos de archivos aceptados y un botón para iniciar la carga y el procesamiento.
Después de procesar el documento, su contenido se muestra en un área dedicada:
<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>
Esta sección proporciona un área desplazable para mostrar el contenido del documento procesado.
El HomeController gestiona la lógica del servidor para importar y procesar documentos Word. Examinemos los métodos clave:
Este método es responsable de gestionar la carga y procesamiento del archivo:
[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
Este método realiza las siguientes tareas:
Valida el archivo subido, asegurándose de que esté en el formato de archivo correcto.(DOC o DOCX)
Verificaciones para la extensión de archivo correcta
Procesa el documento usando la biblioteca IronWord.
Este método privado da formato al contenido extraído en 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
Este método garantiza que el contenido del documento esté correctamente formateado como HTML, con cada línea envuelta en etiquetas de párrafo y las líneas vacías preservadas.
Para manejar la carga de archivos y mostrar el contenido procesado, usamos 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'; }); });
Este código JavaScript maneja el proceso de carga de archivos, envía el archivo al servidor para su procesamiento y actualiza la interfaz de usuario con el contenido procesado o mensajes de error.
La aplicación utiliza CSS personalizado para crear una interfaz atractiva y fácil de usar.
<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>
Este CSS crea un aspecto limpio y moderno con una paleta de colores claros. El área de carga presenta un fondo blanco con efectos de sombra sutiles, mientras que el área de contenido tiene un diseño desplazable con un fondo gris claro. El uso de las propiedades border-radius y box-shadow añade profundidad e interés visual a los elementos de la interfaz.
Mientras continuamos mejorando nuestro procesador de documentos Word, agreguemos la capacidad de exportar documentos. Esta función permitirá a los usuarios generar un nuevo documento de Word desde nuestra aplicación.
Primero, añadiremos una opción de "Exportar" a nuestra barra de navegación. Abra el archivo _Layout.cshtml en la carpeta Views/Shared y localice el
elemento. Agreguemos un nuevo elemento de lista para nuestra función de exportación:<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>
Estamos utilizando Font Awesome para el icono, así que asegúrate de que tengamos el enlace CSS en nuestro.
sección. Este código añade un enlace de "Exportar" a la barra de navegación. Utiliza Font Awesome para el ícono y llama al exportDocument() función al hacer clic. El href="#"** y return false evitan el comportamiento predeterminado del enlace.Ahora, añadamos la función de JavaScript que gestionará el proceso de exportación. 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>
Esta función de JavaScript envía una solicitud POST de AJAX al servidor para crear un documento de Word. En caso de éxito, solicita al usuario un nombre de archivo y luego crea un enlace temporal para descargar el archivo. El enlace se hace clic automáticamente y luego se elimina del DOM. Si hay un error en cualquier etapa, se muestra una alerta al usuario.
Ahora, implementemos la lógica del lado del servidor. Abre el archivo HomeController.cs en la carpeta Controllers. Añadiremos dos nuevos métodos para manejar el proceso de exportación.
Primero, añadamos el método para crear el documento de 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
Este método crea un nuevo documento de Word utilizando la biblioteca IronWord, añade texto de prueba y lo guarda en un archivo temporal con un nombre único. Devuelve un objeto JSON con el estado de éxito y la ruta al archivo temporal. Si ocurre un error, registra la excepción y devuelve un mensaje de error.
A continuación, agreguemos el método para manejar la descarga del archivo:
[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
Este método recupera el archivo temporal creado por ExportWordDocument, lee su contenido en una matriz de bytes y luego elimina el archivo temporal. Utiliza el nombre de archivo proporcionado por el usuario o un nombre predeterminado si no se proporciona ninguno. El método luego devuelve el contenido del archivo como un documento de Word descargable. Si el archivo no se encuentra o si ocurre un error, se devuelven las respuestas HTTP apropiadas.
Para mejorar el aspecto general de nuestro Procesador de Documentos Word, hemos agregado CSS personalizado directamente en el archivo _Layout.cshtml. Veamos el estilo que hemos implementado:
<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>
Este bloque de CSS define el esquema de color y el diseño de nuestra aplicación. Estamos utilizando variables CSS(propiedades personalizadas)para crear una paleta de colores consistente en toda la aplicación. Los estilos están dirigidos a varios elementos, incluyendo el cuerpo, la barra de navegación y el pie de página, asegurando un diseño coherente. Hemos configurado la barra de navegación con un aspecto limpio y moderno, con efectos de desplazamiento e integración de iconos. W
mientras nuestra aplicación actualmente se centra en documentos de Word, podemos usarIronPDFincluir soporte para documentos PDF para expandir su funcionalidad y abarcar una gama más amplia de tipos de archivos. El sistema podría ampliarse para permitir a los usuarios exportar sus documentos como un archivo PDF además de las opciones de formato Word actuales.
Comencemos ejecutando nuestra aplicación WordDocumentProcessor. Como podemos ver en la imagen, la aplicación se ha cargado exitosamente en el navegador. La interfaz es limpia y fácil de usar, con una barra de navegación en la parte superior que muestra las opciones "Inicio" y "Exportar". El área de contenido principal muestra el título "Word Document Processor" y una breve descripción: "Sube y procesa tus documentos de Word con facilidad."
Ahora, intentemos importar un documento. En la imagen, podemos ver que hemos seleccionado un archivo llamado "Honey research synopsis.docx". El nombre del archivo se muestra en el área de carga, reemplazando el botón "Elegir archivo". Ahora estamos listos para cargar y procesar este documento.
Después de hacer clic en "Subir y Procesar", la aplicación procesa el documento y muestra su contenido. La sección "Contenido del Documento" ahora muestra el comienzo del documento subido. Podemos ver el título "Tecnologías de Apicultura y Calidad de la Producción de Miel en Áreas Urbanas" seguido por un resumen. Esto demuestra que nuestra aplicación ha leído y mostrado con éxito el contenido del documento de Word.
Finalmente, probemos la funcionalidad de exportación. En la imagen, vemos un mensaje que aparece cuando hacemos clic en el botón "Exportar" en la barra de navegación. El mensaje nos pide "Ingrese un nombre para el documento"(sin extensión)". El nombre predeterminado "ExportedDocument" está prellenado, pero podemos cambiarlo si lo deseamos. Este mensaje nos permite personalizar el nombre de nuestro documento exportado antes de descargarlo.
Después de hacer clic en "OK", la aplicación genera un nuevo documento de Word con el nombre especificado e inicia el proceso de descarga. Este documento exportado contiene el contenido que hemos procesado o cualquier modificación que hayamos realizado dentro de la aplicación.
A lo largo de este proceso, podemos ver que la aplicación está funcionando como se pretende. Podemos usar esta aplicación para importar documentos de Word, crear documentos y exportarlos con facilidad. La interfaz de usuario es intuitiva y receptiva.
En conclusión, nuestra aplicación WordDocumentProcessor demuestra con éxito el poder y la flexibilidad de integrar el procesamiento de documentos Word en una aplicación web ASP.NET Core. Al aprovechar la biblioteca IronWord, hemos creado una solución robusta para importar, mostrar y exportar documentos de Word con facilidad. Esta aplicación sirve como una base sólida para sistemas de gestión de documentos más complejos o generadores de informes. Para los desarrolladores interesados en explorar las capacidades de IronWord, la biblioteca ofrece un prueba gratuita. Después del período de prueba, las licencias comienzan a partir de $749, convirtiéndolo en una solución rentable para empresas que requieren funcionalidades avanzadas de procesamiento de documentos Word en sus aplicaciones web.
9 productos API .NET para sus documentos de oficina