Import & Export Service

Import/export is provided by the server and allows converting Office files to Univer documents or exporting back to Office formats.

Prerequisites

  • Server deployment completed (see Quick Start)
  • Exchange worker and Temporal are running
  • Object storage is reachable

Import Flow

  1. Upload the file to object storage and get fileID
  2. Call the import API with outputType
    • 1: import as a unit document
    • 2: import as JSON
  3. Poll task status:
    • pending: keep polling
    • done: get import.unitID or import.jsonID
    • failed: read error.message
  4. Document loading

import

Export Flow

The export flow for unit collaborative documents:

  1. Call export API with unitID to get taskID
  2. Poll task status:
    • pending: keep polling
    • done: get export.fileID
    • failed: read error.message
  3. Use export.fileID to Get File download URL

export

The export flow for non-collaborative documents:

  1. Upload the file generated from frontend snapshot JSON to object storage and get fileID
  2. Call export API with jsonID to get taskID; jsonID is the fileID from the previous step
  3. Poll task status:
    • pending: keep polling
    • done: get export.fileID
    • failed: read error.message
  4. Use export.fileID to Get File download URL

Client packages

@univerjs-pro/exchange-client provides the shared request service and Facade download/snapshot utilities. Register the unit-specific client package for the editor you expose:

  • @univerjs-pro/sheets-exchange-client
  • @univerjs-pro/docs-exchange-client
  • @univerjs-pro/slides-exchange-client
  • @univerjs-pro/pdfs-exchange-client
  • @univerjs-pro/bases-exchange-client
  • @univerjs-pro/boards-exchange-client

Import and export request settings are now nested by unit kind:

TypeScript
const importRequest: IImportRequest = {  fileID,  type: univerAPI.Enum.UniverInstanceType.UNIVER_BASE,  outputType: ImportOutputType.JSON,  options: {    base: {      xlsx: {        baseMode: ExchangeBaseImportMode.AUTO,        baseFormulaPolicy: ExchangeBaseFormulaPolicy.CONVERT_THEN_VALUES,      },    },  },}

Base export options similarly use options.base.csv.tableId or options.base.xlsx with ExchangeBaseExportMode and ExchangeBaseFormulaPolicy. Sheet options live under options.sheet.

Implementation Example

The API calls for import/export are already integrated in the frontend, see Facade API for details.

The snippets below demonstrate a complete TypeScript workflow using fetch. Replace BASE_URL with your Univer server endpoint and include the required auth header (for example cookie or Authorization) in every request.

1. Upload a file

TypeScript
async function uploadFile(file: File): Promise<string> {  const formData = new FormData()  formData.append('file', file)  const res = await fetch(    `${BASE_URL}/universer-api/stream/file/upload?size=${file.size}`,    {      method: 'POST',      headers: {        // Add your auth header here, e.g.        // cookie: '_univer=XXXXXX',      },      body: formData,    },  )  const data = await res.json()  if (data.error?.code !== 1) {    throw new Error(data.error?.message || 'Upload failed')  }  return data.FileId // used as fileID in the next step}

2. Poll task status

TypeScript
interface TaskResult {  status: 'pending' | 'done' | 'failed'  error?: { code: number, message: string }  import?: { unitID?: string, jsonID?: string }  export?: { fileID?: string }}async function pollTask(taskID: string, interval = 2000): Promise<TaskResult> {  while (true) {    const res = await fetch(      `${BASE_URL}/universer-api/exchange/task/${taskID}`,      {        headers: {          // cookie: '_univer=XXXXXX',        },      },    )    const data: TaskResult = await res.json()    if (data.status === 'done' || data.status === 'failed') {      return data    }    await new Promise(resolve => setTimeout(resolve, interval))  }}

3. Import a file

TypeScript
interface ImportParams {  fileID: string  type: UniverInstanceType  outputType: 1 | 2 // 1 = unit, 2 = json  options?: IExchangeImportOptions}async function importFile(params: ImportParams): Promise<string> {  const res = await fetch(    `${BASE_URL}/universer-api/exchange/${params.type}/import`,    {      method: 'POST',      headers: {        'Content-Type': 'application/json',        // cookie: '_univer=XXXXXX',      },      body: JSON.stringify({        fileID: params.fileID,        outputType: params.outputType,        options: params.options,      }),    },  )  const data = await res.json()  if (data.error?.code !== 1) {    throw new Error(data.error?.message || 'Import request failed')  }  // Poll until the task is done or failed  const taskResult = await pollTask(data.taskID)  if (taskResult.status === 'failed') {    throw new Error(taskResult.error?.message || 'Import failed')  }  return params.outputType === 1    ? taskResult.import!.unitID!    : taskResult.import!.jsonID!}

4. Export a file

TypeScript
interface ExportParams {  unitID?: string  jsonID?: string  type: UniverInstanceType  format: ExchangeFormat  options?: IExchangeExportOptions}async function exportFile(params: ExportParams): Promise<string> {  const res = await fetch(    `${BASE_URL}/universer-api/exchange/${params.type}/export`,    {      method: 'POST',      headers: {        'Content-Type': 'application/json',        // cookie: '_univer=XXXXXX',      },      body: JSON.stringify({        ...params,      }),    },  )  const data = await res.json()  if (data.error?.code !== 1) {    throw new Error(data.error?.message || 'Export request failed')  }  const taskResult = await pollTask(data.taskID)  if (taskResult.status === 'failed') {    throw new Error(taskResult.error?.message || 'Export failed')  }  // Get a signed download URL  const urlRes = await fetch(    `${BASE_URL}/universer-api/file/${taskResult.export!.fileID!}/sign-url`,    {      headers: {        // cookie: '_univer=XXXXXX',      },    },  )  const urlData = await urlRes.json()  if (urlData.error?.code !== 1) {    throw new Error(urlData.error?.message || 'Failed to get download URL')  }  return urlData.url}

API Reference

How is this guide?

© 2026 DreamNum Co., Ltd.