Skip to main content

Object Storage SDK

ONES provides plugins Storage capabilities.

ONES Entity Storage SDK allows you to query the data stored in these structures using various query conditions, or perform data management operations such as creating, updating, and deleting data.

Currently supported storage capabilities include:

Requirements​

ONES@ones-op/sdk@ones/cli
v6.36.0v1.50.0v1.50.0

Object Storage SDK​

Upload/Update an object​

Uploading an object requires two steps:

  • Step 1: Use the SDK to obtain the upload address and parameters.
  • Step 2: Use the upload address and parameters (including the target file) to upload the object.

Upload pre-signing​

Example usage:

backend/src/index.ts
import { storage } from '@ones-op/sdk/backend'
import type { ObjectStoreUploadResult } from '@ones-op/sdk/backend'

const { object } = storage

const result = <ObjectStoreUploadResult>await object.upload('cover')
// Request on plugin backend
const url = result.getUrl()
// Request on plugin frontend
const webUrl = result.getWebUrl()
// The FormData parameter of the request
const fields = result.getFields()

Return type:

backend/src/index.ts
type result = {
getUrl(): string // Request on plugin backend
getWebUrl(): string // Request on plugin frontend
getFields(): ObjectResultDataFields // The FormData parameter of the request
}
type ObjectResultDataFields = Record<string, string>

Upload an object (backend)​

The specific upload method is implemented by the business.

Example usage:

  • url, obtained through result.getUrl().
  • data, create an instance of FormData.
    • FormData, in Node.js, you need to implement FormData yourself.
      • Or use a third-party library from the community, such as formdata-node@5.0.1.
    • fields, get them through result.getFields() and pass them through one by one.
      • If the key of fields is missing or its content is modified, verification will fail.
    • file, the binary data and file name of the uploaded object.
      • If your file is base64 or Buffer, you can convert it to Blob type data.
  • method, set to post.
  • headers, set Content-Type to multipart/form-data.
  • The status of a successful upload is 201.
backend/src/index.ts
import { FormData } from 'formdata-node' // formdata-node@5.0.1
import { storage } from '@ones-op/sdk/backend'
import type { ObjectStoreUploadResult } from '@ones-op/sdk/backend'

const { object } = storage

const result = <ObjectStoreUploadResult>await object.upload('cover')

// case: 'https://example.com/upload/'
const url = result.getUrl()
// case: { Policy: 'policy', ... }
const fields = result.getFields()

const form = new FormData()
Object.keys(fields).forEach((key) => {
const value = fields[key]
form.append(key, value)
})
const blob = new Blob([buffer]) // cover blob data
form.append('file', blob, 'cover')

// axios or fetch or any request methods
axios({
url,
data: form,
method: 'post',
headers: {
'Content-Type': 'multipart/form-data',
},
}).then((response) => {
console.log(response)
if (response.status === 201) {
console.log('uploaded successfully')
}
})

Upload an object (frontend)​

The specific upload method is implemented by the business.

Example usage:

  • url, obtained through result.getWebUrl().
    • You need to implement an addition interface.
    • First call the SDK method, and then return the result to the plug-in front end.
    • The address may be an absolute path or a relative path. For details, please refer to: Instructions for using webUrl.
  • data, create an instance of FormData.
    • fields, get them through result.getFields() and pass them through one by one.
      • You need to implement an addition interface.
      • First call the SDK method, and then return the result to the plug-in front end.
      • If the key of fields is missing or its content is modified, verification will fail.
    • file, obtained through <input type="file">.
  • method, set to post.
  • headers, set Content-Type to multipart/form-data.
  • The status of a successful upload is 201.
backend/src/index.ts
import { storage } from '@ones-op/sdk/backend'
import type { ObjectStoreUploadResult } from '@ones-op/sdk/backend'

const { object } = storage

export async function hello() {
const result = <ObjectStoreUploadResult>await object.upload('cover')
return {
body: {
url: result.getWebUrl(),
fields: result.getFields(),
}
}
}
web/src/example/index.tsx
import { OPFetch } from '@ones-op/fetch'

const handleClick = async () => {
const response = await OPFetch.post('/project/api/project/hello')

// case1: 'https://example.com/upload/'
// case2: '/upload/'
const url = response.data.data.url
// case: { Policy: 'policy', ... }
const fields = response.data.data.fields

const form = new FormData()
Object.keys(fields).forEach((key) => {
const value = fields[key]
form.append(key, value)
})
const input = document.querySelector('input')
const file = input!.files?.[0] // file from <input type="file">
form.append('file', file!)

// axios or fetch or any request methods
axios({
url,
data: form,
method: 'post',
headers: {
'Content-Type': 'multipart/form-data',
},
}).then((response) => {
console.log(response)
if (response.status === 201) {
console.log('uploaded successfully')
}
})
}

Download an object​

Downloading an object requires two steps:

  • Step 1: Use the SDK to obtain the download address.
  • Step 2: Use the download address to download the object.

Download pre-signature​

Example usage:

backend/src/index.ts
import { storage } from '@ones-op/sdk/backend'
import type { ObjectStoreDownloadResult } from '@ones-op/sdk/backend'

const { object } = storage

const result = <ObjectStoreDownloadResult>await object.download('cover')
// Request on plugin backend
const url = result.getUrl()
// Request on plugin frontend
const webUrl = result.getWebUrl()

Return type:

backend/src/index.ts
type result = {
getUrl(): string // Request on plugin backend
getWebUrl(): string // Request on plugin frontend
}

Download an object (backend)​

The specific download method is implemented by the business.

Example usage:

  • url, obtained through result.getUrl().
  • method, set to get.
backend/src/index.ts
import { storage } from '@ones-op/sdk/backend'
import type { ObjectStoreDownloadResult } from '@ones-op/sdk/backend'

const { object } = storage

const result = <ObjectStoreDownloadResult>await object.download('cover')

// case: 'https://example.com/download/'
const url = result.getUrl()

// axios or fetch or any request methods
axios({
url,
method: 'get',
}).then((response) => {
console.log(response)
})

Download an object (frontend)​

The specific download method is implemented by the business.

  • The file name of the downloaded file can be customized using the download attribute of the <a> tag.

Example usage:

  • url, obtained through result.getWebUrl().
    • You need to implement an addition interface.
    • First call the SDK method, and then return the result to the plug-in front end.
    • The address may be an absolute path or a relative path. For details, please refer to: Instructions for using webUrl.
backend/src/index.ts
import { storage } from '@ones-op/sdk/backend'
import type { ObjectStoreDownloadResult } from '@ones-op/sdk/backend'

const { object } = storage

export async function hello() {
const result = <ObjectStoreDownloadResult>await object.download('cover')
return {
body: {
url: result.getWebUrl(),
}
}
}
web/src/example/index.tsx
import { OPFetch } from '@ones-op/fetch'

const handleClick = async () => {
const response = await OPFetch.post('/project/api/project/hello')

// case1: 'https://example.com/download/'
// case2: '/download/'
const url = response.data.data.url

const a = document.createElement('a')
a.href = url
a.setAttribute('download', 'cover')
a.click()
}

Preview a file or image (frontend)​

The specific preview method is implemented by the business.

  • The browser does not support the preview file type, and the business needs to implement the preview logic.
  • If the file address is opened in the browser, the default behavior is downloading.

Example usage:

  • url, obtained through result.getWebUrl().
    • You need to implement an addition interface.
    • First call the SDK method, and then return the result to the plug-in front end.
    • The address may be an absolute path or a relative path. For details, please refer to: Instructions for using webUrl.
backend/src/index.ts
import { storage } from '@ones-op/sdk/backend'
import type { ObjectStoreDownloadResult } from '@ones-op/sdk/backend'

const { object } = storage

export async function hello() {
const result = <ObjectStoreDownloadResult>await object.download('cover')
return {
body: {
url: result.getWebUrl(),
}
}
}
web/src/example/index.tsx
import { OPFetch } from '@ones-op/fetch'

const response = await OPFetch.post('/project/api/project/hello')

// case1: 'https://example.com/download/'
// case2: '/download/'
const url = response.data.data.url

const preview = <img src={url}></img>

Delete an object​

Example usage:

backend/src/index.ts
import { storage } from '@ones-op/sdk/backend'

const { object } = storage

object.delete('cover')

Get an object metadata​

Example usage:

backend/src/index.ts
import { storage } from '@ones-op/sdk/backend'
import type { ObjectMetadataResultData } from '@ones-op/sdk/backend'

const { object } = storage

const data = <ObjectMetadataResultData>await object.metadata('cover')
console.log(data.object_key)
console.log(data.size)

Return type:

backend/src/index.ts
type data = {
object_key: string
size: number
}

SDK use specification​

Pre-signature validity period​

The pre-signature address is valid for 1 hour. Re-signature is required after expiration.

The time starts from the call to the SDK.

Instructions for using webUrl​

Depending on the deployment of the ONES instance, webUrl may be an absolute path or a relative path.

If you are uploading or downloading an object in a browser, the browser will automatically fill it in based on the current ONES host.

web/src/example/index.tsx
// case1: absolute url
axios({
url: 'https://example.com/upload/',
data: form,
method: 'post',
headers: {
'Content-Type': 'multipart/form-data',
},
})

// case2: relative url
// case2 is the same as case1 when host is https://example.com
axios({
url: '/upload/',
data: form,
method: 'post',
headers: {
'Content-Type': 'multipart/form-data',
},
})

If you are in a script, uploading or downloading objects, you need to fill in the host manually.

let url = result.getWebUrl()
if (/^\//.test(url)) {
const host = 'https://example.com'
url = `${host}${url}`
}

SDK error handling​

All object operations are asynchronous.

For error handling of the following methods, please refer to the example usage:

  • upload
  • download
  • delete
  • metadata

Example usage:

backend/src/index.ts
import { storage } from '@ones-op/sdk/backend'
import type { ObjectError, ObjectStoreUploadResult } from '@ones-op/sdk/backend'

const { object } = storage

// Catching errors
async function hello() {
const result = await object.upload('cover')
if (result instanceof object.ObjectError) {
throw result
}
return {
url: result.getWebUrl(),
fields: result.getFields(),
}
}

// Not catching errors
async function hello() {
const result = <ObjectStoreUploadResult>await object.upload('cover')
return {
url: result.getWebUrl(),
fields: result.getFields(),
}
}

Return type:

backend/src/index.ts
type ObjectError = {
code: string
err_msg: string
}

SDK error code​

Error codeDescription
ObjectKeyInvalidObject key is empty. Or contains illegal characters. Or exceeds maximum length limit.
ObjectKeyNotfoundObject key is not found.
RequestTimeOutRequest timeout.

If an error occurs when uploading or downloading an object, the S3 standard error code is returned. For details, please refer to: S3 error code。