You can use the JavaScript API to preview documents and implement advanced features. These features include full-screen preview, page jump control, UI customization, encrypted document processing, signature refresh, retries, and ad configuration. You can also retrieve document rendering information to view related data.
This document is no longer maintained. Use the new version of Intelligent Media Management.
For a comparison between the new and legacy versions of Intelligent Media Management, see Usage guide for new and legacy versions.
For more information about document processing in the new version of Intelligent Media Management, see WebOffice frontend development.
Full-screen preview
To enable full-screen preview, add the `allowfullscreen` attribute to the iframe on the parent page that contains the preview engine.
<iframe id="preview" src=[PreviewURL] allowfullscreen frameborder="0" scrolling="no"></iframe>
To enable full-screen preview:
function reqFullScreen(){
var el = $('.preview')[0];
var fn = el.requestFullScreen || el.webkitRequestFullScreen || el.mozRequestFullScreen || el.msRequestFullScreen;
fn.call(el);
} Control page jumps for text or presentation documents
// Jump to a specific page.
sendMessage('logic.toPage', {
pageIndex: 0 // The page number to jump to. The index starts from 0.
});
// Go to the previous page.
sendMessage('logic.prevPage');
// Go to the next page.
sendMessage('logic.nextPage');
Customize the UI for text or presentation previews
sendMessage('setConfig', {
writerCustomStyle: function(isMobile) {
if (!isMobile) {
return {
// Top margin of the preview container.
containerMarginTop: 30,
// Bottom margin of the preview container.
containerMarginBottom: 30,
// Background color of the container.
containerBackground: '#000000',
// Spacing between pages.
pageSpacing: 20,
// Shadow style for each page.
pageShadow: '0px 0px 6px 0px rgba(0, 0, 0, 0.3)',
// Border style for each page.
pageBorder: 'none',
// Style for the container of the zoom buttons.
scale: {/* style: Note that the style format here is the same as in a CSS file, for example, vertical-align:middle */},
// Style for the zoom buttons.
scaleBtn: {/* style: Note that the style format here is the same as in a CSS file, for example, vertical-align:middle */},
// Style for the zoom-out button.
scaleShrink: {/* style: Note that the style format here is the same as in a CSS file, for example, vertical-align:middle */},
// Character for the zoom-out button.
scaleShrinkText: '',
// Style for the disabled zoom-out button.
scaleShrinkDisable: {/* style: Note that the style format here is the same as in a CSS file, for example, vertical-align:middle */},
// Style for the zoom-in button.
scaleMagnify: {/* style: Note that the style format here is the same as in a CSS file, for example, vertical-align:middle */},
// Character for the zoom-in button.
scaleMagnifyText: '',
// Style for the disabled zoom-in button.
scaleMagnifyDisable: {/* style: Note that the style format here is the same as in a CSS file, for example, vertical-align:middle */},
// Text for the zoom ratio.
scaleText: {/* style: Note that the style format here is the same as in a CSS file, for example, vertical-align:middle */},
// Sort order of the zoom component elements.
scaleSort: ['shrink', 'text', 'magnify'] // 'shrink' is for zoom-out, 'text' is for the ratio text, and 'magnify' is for zoom-in.
}
} else {
return {
pageBorder: '1px solid #d2d5d8'
};
}
}
});
// Custom styles for presentation preview.
sendMessage('setConfig', {
powerpointCustomStyle: function(isMobile) {
if (!isMobile) {
return {
// Hide the page-turning buttons.
paginationDisplay: false,
// Hide the full-screen button.
fullScreenButtonDisplay: false,
// Top margin of the preview container.
containerMarginTop: 30,
// Bottom margin of the preview container.
containerMarginBottom: 30,
// Background color of the container.
containerBackground: '#000000'
};
} else {
return {};
}
}
});
Customize the error message interface
You can listen for error messages outside the iframe to handle the error UI logic.
sendMessage("setConfig", {
enableMessageUI: false
});
window.addEventListener('message', function(e) {
var res = JSON.parse(e.data);
switch(res.action) {
case 'message.error':
toast(i18n(res.data.result));
break;
}
}, false);
Set up the decryption process for encrypted files
Listen for the `message.error` event to handle the UI for password input. After a user enters the password, resubmit the conversion task with the password. The server then decrypts the file and generates a new preview URL. Set the `src` attribute of the iframe to this new URL. If decryption fails, the child page throws an `aliyunPasswordInvalid` error. The user can then re-enter the password and repeat the process.
sendMessage("setConfig", {
enableCheckPasswordLogic: false
});
var isFirstTime = false;
window.addEventListener('message', function(e) {
var res = JSON.parse(e.data);
switch(res.action) {
case 'message.error':
if (res.data.result === 'aliyunPasswordInvalid') {
if (isFirstTime) {
// Display the password input box.
// Your code.
isFirstTime = false;
} else {
// Prompt that the password is incorrect.
// Your code.
}
}
break;
}
}, false);
Refresh signatures
If a user's local temporary access credential expires, the document preview is interrupted. You must refresh the signature. First, listen for the `logic.refreshToken` event from the child page. Then, retrieve the token information and send a `logic.setToken` message to refresh the signature for the iframe page.
window.addEventListener('message', function(e) {
var res = JSON.parse(e.data);
switch(res.action) {
case 'logic.refreshToken':
// Implement the logic to re-acquire the token yourself.
$.ajax(...).then(function(data){
sendMessage('logic.setToken', {
region: data.region,
accessKeyId: data.accessKeyId,
accessKeySecret: data.accessKeySecret,
stsToken: data.stsToken,
bucket: data.bucket
});
});
break;
...
}
}, false);
Set up a retry mechanism
If a browser preview error occurs, you can set up a retry mechanism. This mechanism attempts to retrieve the OSS document information again to increase the preview success rate.
sendMessage('setConfig', {
couldRetry: function(tryCount) {
// tryCount is the current number of retries.
return new Promise(function(resolve) {
if (tryCount > 35) {
// Maximum number of retries.
resolve(false);
} else {
var tryDelay = 0;
if (tryCount < 2) {
// 0 - 1
tryDelay = 250;
} else if (tryCount <= 11) {
// 2 - 11
tryDelay = 500;
} else {
// 12 - 35
tryDelay = 1000;
}
setTimeout(function () {
resolve(true); // Execute the retry.
}, tryDelay);
}
});
}
});
Customize ads
If `data` is a function, you must pass any variables referenced in the function to the child page using `setData` before you call the function.
// Word document (mobile).
sendMessage('setConfig', {
wordAd: function(pageIndex, total) {
// pageIndex is the current page number and total is the total number of pages. Use these parameters to design the ad display logic.
return {
type: 'iframe', // iframe or img.
src: iframeData.xxx, // All variables in the function must be passed through setData and used via iframeData.
href: iframeData.xxx, // Redirect URL.
width: 1090, // Width.
height: 200, // Height.
closeBtn: true // Specifies whether to display the close button for the ad.
};
}
});
// Excel spreadsheet (mobile and web).
sendMessage('setConfig', {
etAd: function() {
return {
type: 'iframe',
src: 'http://xxxx',
href: '',
width: 1090,
height: 200,
closeBtn: true
}
}
});
// PowerPoint presentation (web).
sendMessage('setConfig', {
wppAd: function() {
return {
type: 'iframe',
src: 'http://xxxx',
href: '',
width: 1090,
height: 200,
closeBtn: true
}
}
});
Calibrate local signature time
The OSS SDK uses the local time by default when it creates a signature. If the local time differs from the server time by more than 15 minutes, signature verification fails. To fix this, you can force the SDK to use the server time for signing. You must implement the logic to retrieve the server time.
sendMessage("setConfig", {
timestamp: {
serverTime: 1540881763, // Current server time. Unit: seconds.
expires: 3600 // Signature validity period. The default value is 1800. Unit: seconds.
}
});
Get preview information
You can listen for messages outside the iframe to retrieve information from the preview page. The message body is a JSON string, such as `{"action":"page.readPage", "data":{"pageIndex":5}}`. In this example, `action` is the event name and `data` is the returned data.
window.addEventListener('message', function(e) {
var res = JSON.parse(e.data);
// res.action
// res.data
});
Record the current page number
You can listen for the `page.readPage` action to retrieve the current page number from `data.pageIndex`. Store this value. The next time you open the same document, you can assign this value to the `pageIndex` parameter in the iframe URL. This allows users to resume viewing from where they left off.
{
"action": "page.readPage",
"data": {
"pageIndex": 0
}
} Get meta.json information
{
action: "preview.meta", // The execution status of the current page.
data: {
version: "xxx", // Data version number.
epc: "xxx", // Number of pages rendered for preview.
pc: "xxx", // Actual number of pages in the document.
pro: "xxx", // File type.
...
}
} Error event descriptions
When an error occurs, the parent window receives a JSON string message with the following data structure.
{
action: 'message.error',
data: {
result: 'aliyunOpenFileFail',
data: {
// Error details.
}
}
}
The value of `action` is always `message.error`. The value of `result` describes the specific error type. For more information, see the following table.
Error type | Description |
aliyunOpenFileFail | Failed to open the document. |
aliyunUnsupportFile | Unsupported file type. |
aliyunRequstFail | The frontend failed to request static resources. This includes signature errors. Detailed information is returned in the data. |
aliyunQueryParamInvalid | A required page parameter is missing. |
aliyunRequestTimeout | Resource loading timed out. |
aliyunRenderEngineTooOld | The JS rendering engine version is too old. |
aliyunPasswordInvalid | Incorrect password. You need to handle the password retry logic. |
Get key information for the rendered page
The parent window receives a JSON string message with the following data structure.
{
action: 'page.getBaseInfoFromServerDone', // The execution status of the current page.
data: {
startTime: 1111,// Start time.
endTime: 1111, // End time.
useTime: 1111, // Time spent.
pageStartTime: 1111 // Start time of the preview page.
}
}
The data for all events in the `page.*Done` format includes the `{startTime, endTime, useTime, pageStartTime}` parameters. The unit of time is milliseconds.
For the events described in the table below, each `page.xxxDone` event has a corresponding `page.xxx` event. The `page.xxx` event is the event that starts the execution of `page.xxxDone`. Unlike `page.xxxDone`, the `page.xxx` event does not include the `endTime` and `useTime` parameters.
Event | Description |
getBaseInfoFromServerDone | Gets basic page information. |
getSheetInfoFromServerDone | Gets basic spreadsheet information. |
getPageInfoFromServerDone | Gets single-page information `{pageIndex: 0, ...}`. |
firstRendered | The first screen is rendered `{startTime, pageStartTime}`. |
timing | For more information, see Timing format. |
The timing format is as follows.
// t is performance.timing.
{
// Time to complete page loading.
loadPage : t.loadEventEnd - t.navigationStart,
// Time for DOM parsing.
domReady : t.domComplete - t.responseEnd,
// Time for redirection.
redirect : t.redirectEnd - t.redirectStart,
// Time for DNS query.
lookupDomain : t.domainLookupEnd - t.domainLookupStart,
// TTFB, which is Time To First Byte.
ttfb : t.responseStart - t.navigationStart,
// Time to complete content loading.
request : t.responseEnd - t.requestStart,
// Time to execute the onload callback function.
loadEvent : t.loadEventEnd - t.loadEventStart,
// Time for DNS cache.
appcache : t.domainLookupStart - t.fetchStart,
// Time to unload the page.
unloadEvent : t.unloadEventEnd - t.unloadEventStart,
// Time to establish a TCP connection and complete the handshake.
connect : t.connectEnd - t.connectStart,
timing: t
}