Một số khách hàng đã tiếp cận chúng tôi và hỏi cách họ có thể tạo ứng dụng web giống như Google Tài liệu bằng API của chúng tôi. Google Docs là một trình xử lý văn bản cho phép người dùng tạo và chỉnh sửa tệp trực tuyến trong khi cộng tác với những người dùng khác trong thời gian thực.

Bài đăng trên blog này giải thích việc tạo phiên bản rút gọn của Google Tài liệu có các tính năng sau dễ dàng như thế nào:

  • Chỉnh sửa văn bản đa dạng thức (thay đổi phông chữ, kích thước, màu sắc, kiểu văn bản (in đậm, in nghiêng), căn chỉnh, v.v.).
  • Chỉnh sửa cộng tác theo thời gian thực của cùng một tài liệu. Nhiều người dùng có thể truy cập tài liệu cùng một lúc và sửa đổi nó.
  • Tải nội dung của Tài liệu Word hiện có lên trình chỉnh sửa.
  • Lưu văn bản trong trình chỉnh sửa dưới dạng tài liệu MS Word, PDF, TXT hoặc HTML.

Sản phẩm cuối cùng của chúng ta sẽ trông như sau:

Google Documents giống như Giao diện ứng dụng

Công cụ và Công nghệ – Tạo ứng dụng giống như Google Docs

Chúng tôi sẽ phát triển ứng dụng web giống như Google Docs trong ASP.NET Core và sử dụng hai thư viện sau:

  • bàn lửa is an open-source, collaborative text editor. It uses the Firebase Realtime Database as a backend so it requires no server-side code and can be added to any web app simply by including the JavaScript files.
  • GroupDocs.Editor cho .NET gives us an ability to edit most popular document formats using any WYSIWYG editor without any additional applications. We will load document via GroupDocs.Editor into Firepad, edit document in a way we want and save it back to original document format.

Tôi đã sử dụng Visual Studio cho Mac làm IDE. Tuy nhiên, bạn có thể tải xuống phiên bản cộng đồng miễn phí của Visual Studio, tùy thuộc vào nền tảng của bạn, từ đây. Hãy bắt đầu.

Tạo dự án Ứng dụng web ASP.NET Core mới và đặt tên dự án là “GoogleDocsLite".

Tạo một ứng dụng web ASP.NET Core mới

Chạy ứng dụng để đảm bảo mọi thứ được thiết lập đúng cách.

Tích hợp Firepad

Chúng tôi có thể thêm Firepad vào ứng dụng web của mình bằng cách đưa các tệp JavaScript sau vào phần của Layout.cshtml.

<!-- Firebase -->
<script src="https://www.gstatic.com/firebasejs/7.13.2/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/7.13.2/firebase-auth.js"></script>
<script src="https://www.gstatic.com/firebasejs/7.13.2/firebase-database.js"></script>

<!-- CodeMirror -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.17.0/codemirror.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.17.0/codemirror.css" />

<!-- Firepad -->
<link rel="stylesheet" href="https://firepad.io/releases/v1.5.9/firepad.css" />
<script src="https://firepad.io/releases/v1.5.9/firepad.min.js"></script>

<!-- userlist -->
<script src="~/js/firepad-userlist.js"></script>
<link rel="stylesheet" href="~/css/firepad-userlist.css" />

Để tạo Firepad, chúng tôi sẽ khởi tạo Firebase, CodeMirror và sau đó là Firepad. Thêm tập lệnh và mã HTML sau vào Index.cshtml.

<script>
    function init() {
        // Initialize Firebase.
        // TODO: replace with your Firebase project configuration.
        var config = {
            apiKey: '',
            authDomain: "",
            databaseURL: ""
        };
        firebase.initializeApp(config);
        
        // Get Firebase Database reference.
        var firepadRef = getExampleRef();
        
        // Create CodeMirror (with lineWrapping on).
        var codeMirror = CodeMirror(document.getElementById('firepad'), { lineWrapping: true });

        // Create a random ID to use as our user ID (we must give this to firepad and FirepadUserList).
        var userId = Math.floor(Math.random() * 9999999999).toString();

        // Create Firepad (with rich text features and our desired userId).
        var firepad = Firepad.fromCodeMirror(firepadRef, codeMirror,
                    { richTextToolbar: true, richTextShortcuts: true, userId: userId });

        // Create FirepadUserList (with our desired userId).
        var firepadUserList = FirepadUserList.fromDiv(firepadRef.child('users'),
        document.getElementById('userlist'), userId);
    }
    
    // Helper to get hash from end of URL or generate a random one.
    function getExampleRef() {
        var ref = firebase.database().ref();
        var hash = window.location.hash.replace(/#/g, '');
        if (hash) {
            ref = ref.child(hash);
        } else {
            ref = ref.push(); // generate unique location.
            window.location = window.location + '#' + ref.key; // add it as a hash to the URL.
        }
        if (typeof console !== 'undefined') {
            console.log('Firebase data: ', ref.toString());
        }
        return ref;
    }
</script>

<div id="userlist"></div>
<div id="firepad"></div>

Vui lòng thay thế nội dung của config bằng config.

Chúng tôi muốn đoạn mã trên được thực thi khi trang web đã tải hoàn toàn tất cả nội dung (tệp tập lệnh, tệp CSS, v.v.). Vì vậy, hãy gọi hàm init() từ thuộc tính sự kiện onLoad của phần tử trong Layout.cshtml.

<body onload="init()">

của bạn<body> phần tử sẽ trông như sau. Nếu nó chứa các thẻ không cần thiết như <header> , <footer> , vui lòng loại bỏ chúng.

Yếu tố cơ thể

Nếu bạn chạy dự án, bạn sẽ nhận thấy rằng firepad và danh sách người dùng không được căn chỉnh chính xác. Vui lòng sử dụng mã CSS sau để điều chỉnh kích thước/vị trí của firepad và danh sách người dùng. Bạn có thể thêm đoạn mã sau vào trong phần tử của Layout.cshtml.

<style>
    html {
        height: 100%;
    }

    body {
        margin: 0;
        height: 100%;
    }

    /* We make the user list 175px and firepad fill the rest of the page. */
    #userlist {
        position: absolute;
        left: 0;
        top: 50px;
        bottom: 0;
        height: auto;
        width: 175px;
    }

    #firepad {
        position: absolute;
        left: 175px;
        top: 50px;
        bottom: 0;
        right: 0;
        height: auto;
    }
</style>

Firepad đã được thiết lập thành công.

Tải nội dung của tài liệu Word hiện có lên Trình chỉnh sửa

Bây giờ chúng tôi muốn cung cấp cho người dùng cách tải lên nội dung của Tài liệu Word đang thoát trong trình soạn thảo văn bản. Trên giao diện người dùng, chúng tôi thêm một phần tử của loại tệp cho phép người dùng chọn Tài liệu Word từ máy cục bộ của họ. Ở phần phụ trợ, chúng tôi sử dụng thư viện GroupDocs.Editor để truy xuất nội dung của Tài liệu Word dưới dạng chuỗi HTML. Cuối cùng, chúng tôi sử dụng phương thức setHtml() của Firepad để hiển thị nội dung trong trình soạn thảo văn bản.

Thêm những điều sau phần tử trong tệp Index.cshtml trước nhãn.

<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" />
</form>

Trong tệp Index.cshtml.cs, xác định thuộc tính tương ứng.

[BindProperty]
public IFormFile UploadedDocument { get;  set; }

Chạy dự án và nhấp vào nút Chọn tệp. Chọn Tài liệu Word mà bạn muốn tải lên và nhấp vào nút Tải lên Tài liệu. Sẽ không có gì xảy ra vì chúng ta chưa xác định trình xử lý trong Index.cshtml.cs. Trước khi thực hiện việc này, trước tiên hãy thêm thư viện GroupDocs.Editor vào dự án của chúng ta.

Tích hợp GroupDocs.Editor

GroupDocs.Editor có sẵn dưới dạng gói NuGet để chúng ta có thể dễ dàng thêm nó vào dự án của mình. Nhấp chuột phải vào dự án và chọn tùy chọn Quản lý gói NuGet. Cửa sổ Quản lý gói NuGet sẽ mở, chọn tab Duyệt và nhập GroupDocs.Editor vào trường tìm kiếm. GroupDocs.Editor sẽ xuất hiện dưới dạng kết quả đầu tiên, hãy chọn kết quả đó rồi nhấp vào nút Thêm gói.

Thêm GroupDocs.Editor thông qua Trình quản lý gói NuGet

Khi gói được thêm thành công, nó sẽ xuất hiện trong thư mục con NuGet trong thư mục Phụ thuộc.

Xử lý dữ liệu biểu mẫu

Bây giờ chúng ta viết một trình xử lý (phương thức OnPostUploadDocument()) sẽ được gọi khi người dùng nhấp vào nút Tải tài liệu lên. Đối tượng Tài liệu tải lên (thuộc loại IFormFile) chứa nội dung của tài liệu được tải lên. Đầu tiên, chúng tôi lưu tài liệu trên máy chủ, sau đó sử dụng thư viện GroupDocs.Editor để lấy nội dung của nó dưới dạng chuỗi HTML. Vui lòng thêm mã sau vào tệp Index.cshtml.cs.

private readonly IWebHostEnvironment _hostingEnvironment;

public string DocumentContent { get; set; }

public IndexModel(IWebHostEnvironment hostingEnvironment)
{
    _hostingEnvironment = hostingEnvironment;
}

public void OnPostUploadDocument()
{
    var projectRootPath = Path.Combine(_hostingEnvironment.ContentRootPath, "UploadedDocuments");
    var filePath = Path.Combine(projectRootPath, UploadedDocument.FileName);
    UploadedDocument.CopyTo(new FileStream(filePath, FileMode.Create));
    ShowDocumentContentInTextEditor(filePath);
}

private void ShowDocumentContentInTextEditor(string filePath)
{
    WordProcessingLoadOptions loadOptions = new WordProcessingLoadOptions();
    Editor editor = new Editor(filePath, delegate { return loadOptions; }); //passing path and load options (via delegate) to the constructor
    EditableDocument document = editor.Edit(new WordProcessingEditOptions()); //opening document for editing with format-specific edit options

    DocumentContent = document.GetContent();
}

Firepad cung cấp hai sự kiện để nghe. Một trong số chúng ở trạng thái ‘sẵn sàng’ và sẽ kích hoạt sau khi Firepad truy xuất nội dung soạn thảo ban đầu. Chúng tôi đính kèm lệnh gọi lại vào loại sự kiện này và trong lệnh gọi lại, chúng tôi chuyển chuỗi DocumentContent làm đối số cho phương thức setHtml() của đối tượng firepad. Vui lòng thêm đoạn mã sau vào hàm init() trong Index.cshtml.

firepad.on('ready', function() {
    if (firepad.isHistoryEmpty()) {
        var documentContent = '@Model.DocumentContent';
        if (documentContent.length != 0) {   
            firepad.setHtml(htmlDecode(documentContent));
        } else {
            firepad.setText("Welcome to your own private pad! Share the URL above and collaborate with your friends.");
        }
    }
});

Bạn có thể nhận thấy rằng trước tiên chúng ta đã chuyển chuỗi documentContent sang phương thức htmlDecode() trước khi chuyển sang phương thức setHtml(). Đó là thay thế các thực thể ký tự như <, > bằng các dấu (<>). Phương thức htmlDecode() trông như sau.

function htmlDecode(input) {
    var e = document.createElement('div');
    e.innerHTML = input;
    return e.childNodes[0].nodeValue;
}

Chạy dự án, bây giờ bạn sẽ có thể tải nội dung của Tài liệu Word lên trình chỉnh sửa.

Trong phần II của bài đăng này, tôi đã giải thích cách chúng tôi có thể mở rộng ứng dụng của mình để bao gồm các tính năng sau:

  • Tải xuống nội dung của trình chỉnh sửa dưới dạng tài liệu MS Word, PDF, TXT hoặc HTML.
  • Chia sẻ URL với bạn bè để họ có thể chỉnh sửa tài liệu cùng lúc.

Vui lòng xem thử.

Mã nguồn hoàn chỉnh của dự án có sẵn trên GitHub.

Xem thêm