В первом сообщении в блоге мы создали веб-приложение, похожее на Google Документы, со следующими функциями:
- Редактирование расширенного текста (изменение шрифта текста, размера, цвета, стиля (полужирный, курсив), выравнивание и т. д.).
- Совместное редактирование одного и того же документа в режиме реального времени. Несколько пользователей могут одновременно получать доступ к документу и изменять его.
- Загрузите содержимое существующего документа Word в редактор.
В этом сообщении блога мы расширим наше веб-приложение, включив в него следующие функции:
- Загрузите содержимое редактора в виде документа MS Word, PDF, TXT или HTML.
- Поделитесь URL-адресом с друзьями, чтобы они могли одновременно редактировать документ.
Конечный продукт будет выглядеть следующим образом:

- Загрузить содержимое редактора как
- Поделитесь URL-адресом редактора с друзьями
Загрузить содержимое редактора в виде документа Microsoft Word
Сначала мы добавляем <input>
элемент типа отправить в нашу форму, чтобы отобразить кнопку «Загрузить документ» во внешнем интерфейсе. Мы используем атрибут asp-page-handler, чтобы указать обработчик кнопки. Теперь наш элемент формы выглядит следующим образом:
<form method="post" enctype="multipart/form-data" id="uploadForm">
<input asp-for="UploadedDocument" />
<input type="submit" value="Upload Document" class="btn btn-primary" asp-page-handler="UploadDocument" />
<input type="submit" value="Download Document" class="btn btn-primary" asp-page-handler="DownloadDocument" />
<input asp-for="DocumentContent" type="hidden" />
</form>
Вы могли заметить, что мы добавили еще один <input>
элемент скрытого типа. Этот элемент привязан к свойству DocumentContent в Index.cshtml.cs. Мы будем использовать это свойство для хранения содержимого редактора в виде строки HTML.
[BindProperty]
public string DocumentContent { get; set; }
Firepad предоставляет другое событие, синхронизированное для прослушивания. Он запускается, когда наш локальный клиент редактирует документ, и когда эти изменения были успешно записаны в Firebase. Мы присоединяем обратный вызов к этому типу события, чтобы установить значение свойства DocumentContent в firepad.getHtml(). Добавьте следующий код в функцию init() в Index.cshtml.
firepad.on('synced', function (isSynced) {
// isSynced will be false immediately after the user edits
// the pad, and true when their edit has been saved to Firebase.
if (isSynced) {
document.getElementById("DocumentContent").value = firepad.getHtml();
}
});
Теперь реализуем функционал обработчика OnPostDownloadDocument(). Мы используем библиотеку GroupDocs.Editor для сохранения содержимого редактора в виде документа Microsoft Word, который хранится в свойстве DocumentContent. Обработчик возвращает документ Word в качестве ответа пользователю.
public FileResult OnPostDownloadDocument()
{
// Editor object is referencing to the document initially uploaded for editing.
WordProcessingLoadOptions loadOptions = new WordProcessingLoadOptions();
Editor editor = new Editor(UploadedDocumentPath, delegate { return loadOptions; });
// <html>, <head> and <body> tags are missing in the HTML string stored in DocumentContent, so we are adding them manually.
string completeHTML = "<!DOCTYPE html><html><head><title></title></head><body>" + DocumentContent + "</body></html>";
EditableDocument document = EditableDocument.FromMarkup(completeHTML, null);
// Path to the output document
var projectRootPath = Path.Combine(_hostingEnvironment.ContentRootPath, "DownloadedDocuments");
var outputPath = Path.Combine(projectRootPath, Path.GetFileName(UploadedDocumentPath));
// Save the Word Document at the outputPath
WordProcessingSaveOptions saveOptions = new WordProcessingSaveOptions(WordProcessingFormats.Docx);
editor.Save(document, outputPath, saveOptions);
// Return the Word Document as response to the User
var bytes = System.IO.File.ReadAllBytes(outputPath);
return new FileContentResult(bytes, new MediaTypeHeaderValue("application/vnd.openxmlformats-officedocument.wordprocessingml.document"))
{
FileDownloadName = Path.GetFileName(UploadedDocumentPath)
};
}
Переменная UploadedDocumentPath определяется как изменяемая строка для хранения значения пути загруженного документа между сеансами.
static volatile string UploadedDocumentPath;
public void OnPostUploadDocument()
{
var projectRootPath = Path.Combine(_hostingEnvironment.ContentRootPath, "UploadedDocuments");
var filePath = Path.Combine(projectRootPath, UploadedDocument.FileName);
UploadedDocument.CopyTo(new FileStream(filePath, FileMode.Create));
// Retain the path of uploaded document between sessions.
UploadedDocumentPath = filePath;
ShowDocumentContentInTextEditor();
}
Ознакомьтесь со статьями Сохранить документ и Создать EditableDocument из файла или разметки, чтобы узнать больше о классах GroupDocs.Editor.
Запустите проект и протестируйте следующий вариант использования:
- Загрузите содержимое существующего документа Word в редактор, нажав кнопку «Загрузить документ».
- Внесите желаемые изменения в содержимое.
- Нажмите кнопку «Загрузить документ», чтобы загрузить обновленный контент в виде документа Word.
Загрузить содержимое редактора в виде PDF-документа
Нам нужно внести несколько изменений в обработчик OnPostDownloadDocument(), чтобы возвращать PDF-документ в качестве ответа. Мы используем PdfSaveOptions вместо WordProcessingSaveOptions и используем application/pdf в качестве типа MIME.
public FileResult OnPostDownloadDocument()
{
WordProcessingLoadOptions loadOptions = new WordProcessingLoadOptions();
Editor editor = new Editor(UploadedDocumentPath, delegate { return loadOptions; });
string completeHTML = "<!DOCTYPE html><html><head><title></title></head><body>" + DocumentContent + "</body></html>";
EditableDocument document = EditableDocument.FromMarkup(completeHTML, null);
var projectRootPath = Path.Combine(_hostingEnvironment.ContentRootPath, "DownloadedDocuments");
var outputPath = Path.Combine(projectRootPath, Path.GetFileNameWithoutExtension(UploadedDocumentPath) + ".pdf");
PdfSaveOptions saveOptions = new PdfSaveOptions();
editor.Save(document, outputPath, saveOptions);
var bytes = System.IO.File.ReadAllBytes(outputPath);
return new FileContentResult(bytes, new MediaTypeHeaderValue("application/pdf"))
{
FileDownloadName = Path.GetFileNameWithoutExtension(UploadedDocumentPath) + ".pdf"
};
}
Загрузить содержимое редактора в виде простого текстового документа
Чтобы вернуть простой текстовый документ (.txt) в качестве ответа, мы используем класс TextSaveOptions и используем text/plain в качестве типа MIME.
public FileResult OnPostDownloadDocument()
{
WordProcessingLoadOptions loadOptions = new WordProcessingLoadOptions();
Editor editor = new Editor(UploadedDocumentPath, delegate { return loadOptions; });
string completeHTML = "<!DOCTYPE html><html><head><title></title></head><body>" + DocumentContent + "</body></html>";
EditableDocument document = EditableDocument.FromMarkup(completeHTML, null);
var projectRootPath = Path.Combine(_hostingEnvironment.ContentRootPath, "DownloadedDocuments");
var outputPath = Path.Combine(projectRootPath, Path.GetFileNameWithoutExtension(UploadedDocumentPath) + ".txt");
TextSaveOptions saveOptions = new TextSaveOptions();
editor.Save(document, outputPath, saveOptions);
var bytes = System.IO.File.ReadAllBytes(outputPath);
return new FileContentResult(bytes, new MediaTypeHeaderValue("text/plain"))
{
FileDownloadName = Path.GetFileNameWithoutExtension(UploadedDocumentPath) + ".txt"
};
}
Поделитесь URL-адресом редактора с друзьями
Мы должны предоставить пользователям удобный способ скопировать URL-адрес редактора и поделиться им с друзьями. Для этого добавьте <input>
элемент типа text в Index.cshtml.
<div>
<strong>
<label for="shareURL">Edit with Friends: </label>
</strong>
<input type="text" name="shareURL" id="shareURL" size="50">
</div>
Добавьте указанный выше <div>
элемент перед<div id="userlist">
тег. Мы устанавливаем значение этого поля ввода текста в URL-адрес редактора, используя следующую строку кода. Добавьте этот код в функцию init() в Index.cshtml.
document.getElementById("shareURL").value = window.location.origin + window.location.pathname + window.location.hash;
Мы внесем небольшие изменения в наш CSS, чтобы убедиться, что поле ввода текста отображается правильно. Установите верхнюю позицию firepad и списка пользователей на 100 пикселей и добавьте левое поле к полю ввода текста.
#userlist {
position: absolute;
left: 0;
top: 100px;
bottom: 0;
height: auto;
width: 175px;
}
#firepad {
position: absolute;
left: 175px;
top: 100px;
bottom: 0;
right: 0;
height: auto;
}
#uploadForm {
margin: 16px 2px;
}
#shareURL {
margin-left: 123px;
}
Запустите проект, вы должны увидеть текстовое поле, позволяющее скопировать URL-адрес редактора. Поделитесь им с друзьями и редактируйте документ одновременно с ними.
Полный исходный код проекта доступен на GitHub.