All Products
Search
Document Center

Intelligent Media Management:Quick Start: WebOffice Online Document Collaboration

Last Updated:Mar 01, 2026

This guide walks you through integrating the WebOffice service into your web application to enable real-time online document collaboration. By the end, you will have a working page where multiple users can preview and edit documents stored in OSS, with changes synchronized automatically.

Features

Online document collaboration enables multiple users to preview or edit the same document in real time. Key capabilities include:

  • Auto-sync and save -- Document updates are automatically synchronized and saved to avoid content loss.

  • Version history -- Historical versions are saved in real time. You can restore a document to a specified historical version.

  • Cross-platform -- Works on all platforms including mobile phones, computers, and web pages.

  • Easy to use -- Anyone familiar with office software can use online document collaboration with ease.

  • Custom configurations -- Configure component status, events, features for text documents, and features for table documents.

  • Cached preview -- Disable online collaborative editing during a preview to prevent content updates from being displayed. In cached preview mode, online editing does not affect or refresh the content being previewed. For configuration details, see GenerateWebofficeToken API documentation.

Supported file formats

The following file formats are supported for preview and editing. For a complete list of document format limits, see Document limits.

File typePreviewEditing
Documents (Word).doc, .dot, .wps, .wpt, .docx, .dotx, .docm, .dotm, .rtf.doc, .dot, .wps, .wpt, .docx, .dotx, .docm, .dotm
Presentations (PowerPoint).ppt, .pptx, .pptm, .ppsx, .ppsm, .pps, .potx, .potm, .dpt, .dps.ppt, .pptx, .pptm, .ppsx, .ppsm, .pps, .potx, .potm, .dpt, .dps
Spreadsheets (Excel).xls, .xlt, .et, .xlsx, .xltx, .csv, .xlsm, .xltm.xls, .xlt, .et, .xlsx, .xltx, .xlsm, .xltm
PDF files (PDF).pdfNot supported
Note

PDF files support only online preview and do not support editing. You must set the Readonly parameter in the Permission parameter to true.

Architecture

To integrate the WebOffice service of IMM, you need to modify both the server-side and frontend code of your web application.

The original document must be stored in OSS. The frontend calls operations encapsulated on the server to obtain the collaboration URL and AccessToken. Then, the frontend uses JS-SDK to initialize the editor (which dynamically generates an iframe under the specified block element) and sets the AccessToken to enable document preview or editing.

Architecture diagram

Prerequisites

  1. An AccessKey pair is created and obtained. For more information, see Obtain an AccessKey pair.

  2. Object Storage Service (OSS) is activated, a bucket is created, and documents are uploaded to the bucket. For more information, see Upload objects.

  3. Intelligent Media Management (IMM) is activated. For more information, see Activate IMM.

  4. A project is created in the IMM console. For more information, see Create a project.

    Note
  5. If the domain name of the OSS bucket differs from the domain name of the preview service, configure cross-origin resource sharing (CORS) for the bucket to allow access from the preview service domain. For more information, see Configure CORS.

Limitations

LimitationDetails
WebOffice URL cannot be opened directlyThe URL returned by GenerateWebofficeToken cannot be opened in a browser directly. You must use JS-SDK to access it.
AccessToken validityThe AccessToken is valid for 30 minutes. You must open the preview before the AccessToken expires. Otherwise, the preview cannot be opened.
RefreshToken is single-useThe RefreshToken can be used only once and cannot be reused for refreshing.
PDF is preview-onlyPDF files support only online preview, not editing. Set Readonly in Permission to true.
One instance per pageAn HTML page supports only one WebOffice instance for document preview or editing.
Preview vs. edit modeDocument editing and preview call the same API via JS-SDK. To enable preview mode, set the Readonly parameter in Permission to true when calling GenerateWebofficeToken.

Token lifecycle

TokenPurposeValidityRefresh mechanism
AccessTokenAuthenticates JS-SDK requests30 minutesCall RefreshWebofficeToken on the server
RefreshTokenObtains a new AccessToken1 day (single-use)Single-use; each refresh returns a new RefreshToken

JS-SDK calls the RefreshWebofficeToken operation automatically 5 minutes before the token expires. Set the timeout value to greater than 20 minutes (20 x 60 x 1000 milliseconds) to prevent frequent token refreshing. The default token validity period is 30 minutes.

Important

Token refreshing incurs API call charges. For billing details, see IMM Billing.

  • Projects created before May 1, 2023: Charged based on the number of times the collaboration URL is opened.

  • Projects created after May 1, 2023: Charged based on the number of API calls to GenerateWebofficeToken and RefreshWebofficeToken.

Step 1: Set up the server

Encapsulate the GenerateWebofficeToken and RefreshWebofficeToken operations on your server so the frontend can call them directly to obtain the collaboration URL and AccessToken.

The following example uses a project named test-project and an OSS file at oss://test-bucket/test-object.docx.

Call GenerateWebofficeToken to obtain the collaboration URL

Request 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.
}

Response example

{
    "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 (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 RefreshWebofficeToken to refresh the AccessToken

When an AccessToken expires, the frontend must call the RefreshWebofficeToken operation on the server to refresh the AccessToken. The response format is the same as the GenerateWebofficeToken response.

Step 2: Set up the frontend with JS-SDK

Use JS-SDK to mount the collaboration URL to a block element in your HTML page and set the AccessToken.

Import JS-SDK

In the following example, ${x.y.z} is a placeholder for the JS-SDK version number. Replace it with the actual latest version. For version information, 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>

Initialize the JS-SDK

The frontend obtains the tokenInfo object by calling the GenerateWebofficeToken operation encapsulated on your server.

The following example assumes the tokenInfo object has the same structure as the GenerateWebofficeToken response. The server endpoint /getTokenInfo represents your encapsulated GenerateWebofficeToken operation.

// 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 iframe mount point

Note

After the DOMContentLoaded event is triggered, make sure the mount node exists before you perform initialization.

By default, the iframe is mounted to the body element. You can set a custom mount point as follows:

let instance = aliyun.config({
  mount: document.querySelector('#container'),
  url: 'The document collaboration URL' // The document collaboration URL tokenInfo.WebofficeURL from Step 2b.
})

To customize the iframe object, use the instantiated JS-SDK to access the Document Object Model (DOM) object:

var instance = aliyun.config({
    mount: document.querySelector('#container')
   //...
})
console.log(instance.iframe)

Set the token

Set the token to access the collaboration URL. You must call this method again each time the token is refreshed.

Important

The timeout value must be greater than 20 minutes (20 x 60 x 1000 milliseconds). The default token validity period is 30 minutes. JS-SDK refreshes the token 5 minutes before expiry. Setting the timeout too low causes frequent token refreshing and may incur additional charges.

// 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.
})

Set up automatic token refresh

The frontend obtains the tokenInfo object by calling the RefreshWebofficeToken operation encapsulated on your server. The following example assumes the tokenInfo object has the same structure as the RefreshWebofficeToken response.

Pass in a function that obtains the token. When the token validity period times out, JS-SDK automatically calls this function. The function must return a promise object or a plain object containing the new token.

The following example uses the server endpoint /refreshTokenInfo to represent your encapsulated GenerateWebofficeToken operation.

Note

The refreshToken function does not support async functions. Only a promise or a {token, timeout} object can be returned.

// 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
})

Complete example

The following is a complete JS-SDK sample for document preview:

<!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>WebOffice Preview Demo</title>
  <style>
    #container {
      width: 100%;
      height: 100vh;
    }
  </style>
</head>
<body>
  <div id="container"></div>
  <script src="https://g.alicdn.com/IMM/office-js/${x.y.z}/aliyun-web-office-sdk.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script>
  <script>
    (async function() {
      // Step 1: Obtain the collaboration URL and AccessToken from your server.
      var tokenInfo = await $.get('http://example.com/getTokenInfo')

      // Step 2: Cache the tokenInfo for token refreshing.
      let lastTokenInfo = tokenInfo

      // Step 3: Define the token refresh 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){
          $.get('http://example.com/refreshTokenInfo', {
            RefreshToken: lastTokenInfo.RefreshToken,
            AccessToken: lastTokenInfo.AccessToken,
          }).then(function(tokenInfo){
            lastTokenInfo = tokenInfo
            resolve({
              token: tokenInfo.AccessToken,
              timeout: 25 * 60 * 1000,
            })
          })
        })
      }

      // Step 4: Initialize the JS-SDK.
      let instance = aliyun.config({
        mount: document.querySelector('#container'),
        url: tokenInfo.WebofficeURL,
        refreshToken
      })

      // Step 5: Set the initial token.
      instance.setToken({
        token: tokenInfo.AccessToken,
        timeout: 25 * 60 * 1000,
      })
    })()
  </script>
</body>
</html>
Note

Replace ${x.y.z} with the actual JS-SDK version number and replace http://example.com/getTokenInfo and http://example.com/refreshTokenInfo with your actual server endpoints.