This topic describes the features, implementation, and usage of online document collaboration.
Features
Online document collaboration allows multiple users to preview or edit the same document online in real time. This improves work efficiency. The following features are supported:
Document updates are automatically synchronized and saved to avoid the loss of document content.
Historical versions are saved in real time. You can restore a document to a specified historical version.
Applications can be used on all platforms including mobile phones, computers, and web pages.
Anyone who is familiar with office software can use online document collaboration with ease.
Various types of documents can be previewed or edited.
File formats supported for previewing:
Documentations (Word): .doc, .dot, .wps, .wpt, .docx, .dotx, .docm, .dotm, and .rtf.
Presentations (PowerPoint): .ppt, .pptx, .pptm, .ppsx, .ppsm, .pps, .potx, .potm, .dpt, and .dps.
Tables (Excel): .xls, .xlt, .et, .xlsx, .xltx, .csv, .xlsm, and .xltm.
PDF files (PDF): .pdf.
File formats supported for editing:
Documentations (Word): .doc, .dot, .wps, .wpt, .docx, .dotx, .docm, and .dotm.
Presentations (PowerPoint): .ppt, .pptx, .pptm, .ppsx, .ppsm, .pps, .potx, .potm, .dpt, and .dps.
Tables (Excel): .xls, .xlt, .et, .xlsx, .xltx, .xlsm, and .xltm.
Custom configurations are supported for document collaboration, including the configuration of component status, events, features for text documents, and features for table documents.
For more information about the document formats supported for document preview and editing, see Document limits.
If you want to disable online collaborative editing during a document preview or want to prevent content updates from being displayed during a preview, you can use cached preview. In the cached preview mode, online editing does not affect or refresh the content that is being previewed. For more information about how to configure cached preview, see API documentation.
Implementation
To integrate with the WebOffice service of IMM, you need to modify both the server-side and frontend code of your web application.
First, make sure that the original document is stored in OSS. The frontend calls the operations encapsulated on the server to obtain the collaboration URL and AccessToken of the document. Then, the frontend calls js-sdk to initialize (which dynamically generates an iframe under the specified block element) and sets the AccessToken to implement document preview or editing.

Prerequisites
An AccessKey pair is created and obtained. For more information, see Obtain an AccessKey pair.
Object Storage Service (OSS) is activated, a bucket is created, and documents are uploaded to the bucket. For more information, see Upload objects.
Intelligent Media Management (IMM) is activated. For more information, see Activate IMM.
A project is created in the IMM console. For more information, see Create a project.
NoteYou can call the CreateProject operation to create a project. For more information, see CreateProject - Create a project.
You can call the ListProjects - List all project information operation to list all projects created in the specified region.
If the domain name of the OSS bucket is different from that of the preview service, make sure that cross-origin resource sharing (CORS) is configured for the bucket that stores the documents to allow the access from the domain name of the preview service. For more information, see Configure CORS.
Other limits
Document editing and document preview call the same API operation that is provided by JS-SDK. When you call the GenerateWebofficeToken - Obtain a Weboffice token operation to obtain an AccessToken, set the Readonly parameter in the Permission parameter to
truefor preview mode.The URL returned by the GenerateWebofficeToken - Obtain a Weboffice token operation cannot be directly opened. You must use JS-SDK to access the URL.
The AccessToken returned by the GenerateWebofficeToken - Obtain a Weboffice token operation is valid for 30 minutes. You must open the preview before the AccessToken expires. Otherwise, the preview cannot be opened.
The RefreshToken returned by the GenerateWebofficeToken - Obtain a Weboffice token operation can be used only once and cannot be reused for refreshing.
PDF files support only online preview and do not support editing. You must set the Readonly parameter in the Permission parameter to
true.An HTML page supports only one WebOffice instance for document preview or editing.
Usage
Step 1: Encapsulate the operations on the server
Encapsulate the GenerateWebofficeToken - Obtain a Weboffice token and RefreshWebofficeToken - Refresh a Weboffice token operations on the server to obtain the editing URL and AccessToken for the frontend to call directly. The following example describes how to encapsulate the operations for a project named test-project and an OSS file at oss://test-bucket/test-object.docx.
Call the GenerateWebofficeToken - Obtain a Weboffice token operation to obtain the collaboration URL.
Query example
{ "ProjectName": "test-project", // The name of the IMM project. "SourceURI": "oss://test-bucket/test-object.docx", // The URI of the document in OSS. "Filename": "test-object.docx", // The name of the document. "UserData": "{\"fid\": \"123\"}", // The user data, which is returned in the MNS notification. "PreviewPages": 3, // The number of preview pages. "Permission": "{\"Rename\": \"true\", \"Readonly\": \"false\"}", // The permissions. "User": "{\"Id\": \"test\", \"Name\": \"testuser\", \"Avatar\": \"http://xx.com/avatar.jpg\"}", // The user information displayed for online collaboration. "Watermark": "{\"Type\": \"1\", \"Value\": \"imm\"}" // Set a watermark. }Sample response
{ "RefreshToken": "f1fd1afd79ee445f95d3dd99f34f35ffv3", "RequestId": "BC63D209-5E53-00E9-8D24-7043943DBC89", "AccessToken": "3de242da81e1433abefbbea000aaae39v3", "RefreshTokenExpiredTime": "2022-07-06T23:18:52.856132358Z", "WebofficeURL": "https://office-cn-shanghai.imm.aliyuncs.com/office/w/7c1a7b53d6a4002751ac4bbaea69405a01475f4a?_w_tokentype=1", "AccessTokenExpiredTime": "2022-07-05T23:48:52.856132358Z" }Complete sample code (for IMM SDK for Python V1.27.3)
# -*- coding: utf-8 -*- import os from alibabacloud_imm20200930.client import Client as imm20200930Client from alibabacloud_tea_openapi import models as open_api_models from alibabacloud_imm20200930 import models as imm_20200930_models from alibabacloud_tea_util import models as util_models from alibabacloud_tea_util.client import Client as UtilClient class Sample: def __init__(self): pass @staticmethod def create_client( access_key_id: str, access_key_secret: str, ) -> imm20200930Client: """ Use the AccessKey ID and AccessKey secret to initialize a client. @param access_key_id: @param access_key_secret: @return: Client @throws Exception """ config = open_api_models.Config( access_key_id=access_key_id, access_key_secret=access_key_secret ) # Specify the domain name you want to access. config.endpoint = f'imm.cn-shenzhen.aliyuncs.com' return imm20200930Client(config) @staticmethod def main() -> None: # The AccessKey pair of an Alibaba Cloud account has permissions on all API operations. Using these credentials to perform operations is a high-risk operation. We recommend that you use a RAM user to call API operations or perform routine O&M. # We recommend that you do not include your AccessKey pair (AccessKey ID and AccessKey secret) in your project code for data security reasons. # In this example, the AccessKey pair is read from the environment variables to implement identity verification for API access. For information about how to configure environment variables, visit https://www.alibabacloud.com/help/en/imm/developer-reference/configure-environment-variables?spm=a3c0i.29367734.6737026690.8.6d266e9bORGXvg. imm_access_key_id = os.getenv("AccessKeyId") imm_access_key_secret = os.getenv("AccessKeySecret") client = Sample.create_client(imm_access_key_id, imm_access_key_secret) # Set a watermark. weboffice_watermark = imm_20200930_models.WebofficeWatermark( type=1, value='imm' ) # Set the collaborator information. weboffice_user = imm_20200930_models.WebofficeUser( id='test', name='testuser', avatar='http://xx.com/avatar.jpg' ) # Set permissions. weboffice_permission = imm_20200930_models.WebofficePermission( rename=True ) get_weboffice_urlrequest = imm_20200930_models.GenerateWebofficeTokenRequest( # Set the IMM project name. project_name='test-project', # Set the URI of the document for collaboration. source_uri='oss://test-bucket/test-object.docx', # Set the name of the document. filename='test-object.docx', # Set user data. user_data='{"fid": "123"}', preview_pages=3, external_uploaded=False, permission=weboffice_permission, user=weboffice_user, watermark=weboffice_watermark ) runtime = util_models.RuntimeOptions() try: # Print the return value of the API operation. response = client.get_weboffice_urlwith_options(get_weboffice_urlrequest, runtime) print(response.body.to_map()) except Exception as error: # Print the error message if necessary. UtilClient.assert_as_string(error.message) print(error) if __name__ == '__main__': Sample.main()
Call the RefreshWebofficeToken - Refresh a Weboffice token operation to refresh the AccessToken.
When an AccessToken expires, the frontend must call the RefreshWebofficeToken operation on the server to refresh the AccessToken. The format of the response is the same as the format of the response for calling the GenerateWebofficeToken operation.
Step 2: Use JS-SDK in the frontend
Use JS-SDK to mount the returned collaboration URL to a block element in the HTML page and set the AccessToken.
Import JS-SDK.
In the example,
${x.y.z}indicates the latest version number of JS-SDK. Replace it with the actual version number. For information about the latest version, see JS-SDK versions.<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Demo</title> </head> <body> <script src="https://g.alicdn.com/IMM/office-js/${x.y.z}/aliyun-web-office-sdk.min.js"></script> <script> console.log('After importing, the JS-SDK is available for use!'); console.log(aliyun); //Global variable name. </script> </body> </html>Initialization.
The frontend obtains the tokenInfo object by using the GenerateWebofficeToken operation that is encapsulated on the server.
This example assumes that the tokenInfo object has the same structure as the response to the GenerateWebofficeToken operation. The following code uses the encapsulated GenerateWebofficeToken operation
/getTokenInfoon the server as an example.// Obtain the collaboration URL and AccessToken. var tokenInfo = await $.get('http://example.com/getTokenInfo') // Initialization let instance = aliyun.config({ url: tokenInfo.WebofficeURL // Set the document collaboration URL. })Set the mount point for the iframe.
NoteAfter the DOMContentLoaded event is triggered, make sure that the mount node exists before you perform the initialization.
By default, the iframe is mounted to the body element. You can set the mount point for the iframe based on your requirements.
let instance = aliyun.config({ mount: document.querySelector('#container'), url: 'The document collaboration URL' // The document collaboration URL tokenInfo.WebofficeURL in Step 2. })If you need to customize the iframe object, you can use the instantiated JS-SDK to obtain the Document Object Model (DOM) object of the iframe.
var instance = aliyun.config({ mount: document.querySelector('#container') //... }) console.log(instance.iframe)Set the token.
ImportantThe WebOffice online document collaboration for projects that are created before May 1, 2023 is charged based on the number of times the collaboration URL is opened.
The WebOffice online document collaboration for projects that are created after May 1, 2023 is charged based on the number of API calls. You are charged when you call the GenerateWebofficeToken and RefreshWebofficeToken operations.
JS-SDK calls the RefreshWebofficeToken operation to refresh the token 5 minutes before it expires. Therefore, the timeout value must be greater than 20 minutes (20 × 60 × 1000 milliseconds). The default validity period of a token is 30 minutes. This prevents frequent token refreshing and additional fees.
You need to set the token to access the obtained collaboration URL.
You need to set the token by using this method after each token is refreshed.
//https://www.alibabacloud.com/help/en/imm/developer-reference/api-imm-2020-09-30-createsimilarimageclusteringtask?spm=a2c63.p38356.0.i3 // Obtain the token by using an asynchronous request or template output based on your business requirements. var token = 'yourToken'; // Specify the token. instance.setToken({ token: token, timeout: 25 * 60 * 1000, // The token validity period. This parameter is required. Unit: milliseconds. In this example, the token validity period is set to 25 minutes. You can use the refreshToken function to refresh the token 5 minutes before it expires. })Refresh the token after timeout.
The frontend obtains the tokenInfo object by using the RefreshWebofficeToken operation that is encapsulated on the server. This example assumes that the tokenInfo object has the same structure as the response to the RefreshWebofficeToken operation.
You can pass in the function that obtains the token. After the token validity period times out, JS-SDK automatically calls the function and returns a promise object or a common object that contains the new token.
The following example uses the encapsulated GetWebofficeToken operation
/refreshTokenInfoon the server.// Cache the last tokenInfo for token refreshing. let lastTokenInfo = tokenInfo // Obtain the token function. // Note: refreshToken does not support async functions. Only promise or {token,timeout} objects can be returned. const refreshToken = function() { return new Promise(function(resolve){ // The business processing logic. Call the refreshToken operation that is encapsulated on the server. $.get('http://example.com/refreshTokenInfo',{ RefreshToken: lastTokenInfo.RefreshToken, AccessToken: lastTokenInfo.AccessToken, //.... }).then(function(tokenInfo){ lastTokenInfo = tokenInfo resolve({ token: tokenInfo.AccessToken, // This parameter is required. timeout: 25 * 60 * 1000, // The token validity period. This parameter is required. Unit: milliseconds. In this example, the token validity period is set to 25 minutes. You can use the refreshToken function to refresh the token 5 minutes before it expires. }) }) }) } // Configure the function that obtains the token. aliyun.config({ //... refreshToken })
Sample code
See the following complete JS-SDK sample code for document preview: