All Products
Search
Document Center

Intelligent Media Management:Getting started

Last Updated:Dec 11, 2024

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 file formats that WebOffice supports for previewing and editing, see File 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, see GenerateWebofficeToken.

Implementation

The application obtains the URL of document collaboration and AccessToken. JS-SDK is used to generate an iframe under a specified block element and set the AccessToken to preview and edit the document.

Usage notes

  • Document editing and document preview call the same API operation that is provided by JS-SDK. When you call the GenerateWebofficeToken operation to obtain the AccessToken for document preview, set the value of Readonly in the Permission parameter to true.

  • The URL returned by calling the GenerateWebofficeToken operation must be opened by using the JS-SDK.

  • The AccessToken returned by calling the GenerateWebofficeToken operation is valid for 30 minutes. You need to access the URL before the AccessToken expires.

  • The RefreshToken returned by calling the GenerateWebofficeToken operation can be used only once and cannot be reused for AccessToken refresh.

  • PDF documents support only online preview. You must set the value of Readonly in the Permission parameter to true.

  • An HTML page supports only one WebOffice instance for document preview or editing.

Prerequisites

  1. An AccessKey pair is created and obtained. For more information, see Create 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. 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
    • You can call the CreateProject operation to create a project. For more information, see CreateProject.

    • You can call the ListProjects operation to query the existing projects in a specific region. For more information, see ListProjects.

  5. 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 of the preview service. For more information, see Configure CORS.

Procedure

Step 1: Encapsulate the operations on the server

Encapsulate the GenerateWebofficeToken and RefreshWebofficeToken operations on the server to obtain the collaboration URL and AccessToken. The following procedure describes how to encapsulate the operations. In this example, the project name is test-project, and the URL of the document in OSS is oss://test-bucket/test-object.docx.

  1. Call the GenerateWebofficeToken operation to obtain the collaboration URL.

    • Sample request

      {
          "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 (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 the account 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. To avoid security risks, 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. Otherwise, the AccessKey pair may be leaked and the security of all resources within your account may be compromised. 
              # 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, see https://help.aliyun.com/document_detail/2361894.html. 
              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()
  2. Call the RefreshWebofficeToken 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.

  1. Import JS-SDK.

    In the code example, ${x.y.z} is the version number of the latest JS-SDK and needs to be replaced with your actual version of the SDK. For more 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 ('You can start using JS-SDK! ');
        console.log(aliyun); // The global variable name. 
      </script>
    </body>
    </html>
  2. Integrate WebOffice.

    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. In the following sample code, the GenerateWebofficeToken operation is encapsulated on the server as /getTokenInfo.

    // Obtain the collaboration URL and AccessToken. 
    var tokenInfo = await $.get('http://example.com/getTokenInfo')
     
    let instance = aliyun.config({
      url: tokenInfo.WebofficeURL // Set the document collaboration URL. 
    })
    // Set the AccessToken. 
    instance.setToken({
      token: tokenInfo.AccessToken
    })
  3. Set the mount point for the iframe.

    Note

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

    By default, the iframe is mounted to the body element. You can set the mount point for the iframe based on your requirements.

    <div id="container"></div>
    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)
  4. Set the token.

    Important
    • The 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 times the GenerateWebofficeToken and RefreshWebofficeToken operations are called.

    • The JS-SDK calls the RefreshWebofficeToken operation 5 minutes in advance to refresh a token. Therefore, we recommend that you set the timeout to more than 20 × 60 × 1000 milliseconds (20 minutes) to prevent extra charges from frequent token refreshing. The default token validity period is 30 minutes.

    • 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 refresh.

    https://help.aliyun.com/document_detail/611302.htm?spm=a2c4g.478147.0.0.794d5d6dqtWTzI // Obtain the token by using asynchronous requests 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. 
    }) 
  5. 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 ends, JS-SDK automatically calls the function and returns a promise object or a common object that contains the new token.

    In the following sample code, the RefreshWebofficeToken operation is encapsulated on the server as /refreshTokenInfo.

    // Cache the tokenInfo obtained last time for token refresh. 
      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:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Demo</title>
  <meta name="viewport" content="width=device-width,initial-scale=1.0"> 
  <style>
    html,body{
      margin:0;
      height:100%;
    }
    #container{ 
      height: 100%;
      width: 100%; 
    }
    iframe {
      width: 100%;
      height: 100%;
    }
  </style>
</head>
<body>
  <script src="https://g.alicdn.com/IMM/office-js/1.1.15/aliyun-web-office-sdk.min.js"></script>
  <div id="container"></div>
  <script>
    window.onload = init;
    async function init() {
      preview(
        // The preview token that is returned by GenerateWebofficeToken. 
        {
            "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"
        }

      )
    }
    
    function preview(tokenInfo) {
      let mount = document.querySelector('#container');
      let instance = aliyun.config({
        mount,
        url: tokenInfo.PreviewURL || tokenInfo.EditURL || tokenInfo.WebofficeURL,
        mode: 'normal',
        // refreshToken
      });
      instance.setToken({ token: tokenInfo.AccessToken, timeout: 25 * 60 * 1000 });

      instance.on('fileOpen', function(data) {
        console.log(data);
      });

      instance.on('error', (err) => {
        console.log ('An error occurred:', err);
      });

    }
  </script>
</body>
</html>