May 12, 2024

ExportX Figma插件使用说明


快速开始

我们的插件支持 「设计模式」和「Dev模式」, 查看下面视频,快速了解插件使用方式~

导出格式支持与压缩率

我们支持同时压缩多种格式和倍率的图片,但是规则限制在5条以内,图片格式支持:

格式支持节省空间
AVIF≈92%
WEBP≈88%
JPG≈85%
PNG≈68%
SVG≈8%
ico🚧 开发中-
💡

压缩效果根据统计得出,实际效果可能有所不同,此表格将持续更新。

历史记录

插件压缩的图片我们会在您的电脑上永久的存储起来,直到您清空缓存或者清除历史纪录。

受限于客户端存储限制,我们仅保存15条历史纪录。

免费图床服务

ExportX为您提供了能够快速上传的免费图床,服务建立在Cloudflare的免费CDN上,我们保证不删除您的图片。方便您0配置即可获得上传体验。

打开插件右上角的开关,即可使用我们的免费图床服务。

此时,点击”ExportX”按钮,一键完成压缩、上传操作。在历史记录中,点击复制按钮,即可获得图片链接。

使用我们的免费图床需要遵守我们的相关协议。

当然,我们更推荐您使用自定义上传服务。

自定义上传服务

如果您有自己的对象存储服务,您可以通过替换成自己的上传接口。 首先,点击左上角的[设置],在上传设置中,选择”自定义”方式。

ImageImage

上传接口规范

开启自定义上传后,图片会通过POST请求上传到您的接口。接口需要遵守以下规范:

Request内容

Header: 您可以通过自定义header来传递token等信息。

Content-Type: multipart/form-data;

Body: 插件通过form-data的方式上传文件,下面的参数是插件提供的,同时,您可以通过自定义Body来传递额外的信息。

参数名类型说明
fileFile二进制文件
fileNameString文件名,如image92.avif
formatString图片格式,如png
figmaNameStringFigma用户名,用户可以在Figma中修改,不是唯一的,但具有可读性。
figmaIdStringFigma用户ID ,19位的数字,参考Figma User
xidString组合字段,格式为figmaName@figmaId

Response内容

您需要给插件返回一个json对象,包含图片的url,url用于复制到剪贴板,如果没有返回url,复制按钮将不可用。

{
  "url": "https://dev.cdn.abfree.com/images/6FjJoXmt34ox0Fu1.png"
}

Cloudflare R2+Worker

示例代码,此处使用hono来演示

import {Hono} from 'hono'

type Bindings = {
  MY_BUCKET: R2Bucket
  CDN_URL: string
}

const app = new Hono<{
  Bindings: Bindings
}>()

app.post('/upload', async (c) => {
  const key = genFileKey()
  const formData = await c.req.parseBody()
  const file = formData['file']

  if (file instanceof File) {
    const fileBuffer = await file.arrayBuffer()
    const fullName = file.name
    const ext = fullName.split('.').pop()
    const path = `images/${key}.${ext}`

    let contentType = file.type
    
    if (contentType === 'image/svg') {
      contentType = 'image/svg+xml'
    }

    console.log(file.type)
    await c.env.MY_BUCKET.put(path, fileBuffer, {
      httpMetadata: {
        contentType: contentType,
        contentDisposition: `inline`
      },
    })
    return c.json({
      'url': `${c.env.CDN_URL}/${path}`
    })
  } else {
    return c.text('Invalid file', 400)
  }
})

Amazon S3 或兼容S3

大多数对象存储都兼容S3协议,比如

  • AWS S3
  • Cloudflare R2
  • Google Cloud Storage
  • 阿里云OSS
  • 腾讯云COS

示例代码

// api.ts
import {Hono} from 'hono'
import {uploadToS3} from "./s3";

type Bindings = {
  CDN_URL: string
}

const app = new Hono<{
  Bindings: Bindings
}>()

app.post('/uploadS3',async (c)=>{
  const key = genFileKey()
  const formData = await c.req.parseBody()
  const file = formData['file']
    if (file instanceof File) {
      const fileBuffer = await file.arrayBuffer()
      const fullName = file.name
      const ext = fullName.split('.').pop()
      const path = `images/${key}.${ext}`
      let contentType = file.type
      if (contentType === 'image/svg') {
        contentType = 'image/svg+xml'
      }
      const uint8Array = new Uint8Array(fileBuffer)
      await uploadToS3(c, {
        file:uint8Array,
        contentType,
        key:key
      })
      return c.json({
        'url': `${c.env.CDN_URL}/${path}`
      })
    } else {
      return c.text('Invalid file', 400)
    }
})

// s3.ts
import {S3} from "@aws-sdk/client-s3";
import {Context} from "hono";

let s3Client: S3
interface UploadParams {
  file: Uint8Array
  contentType: string
  key: string
}
export async function uploadToS3(c: Context, params:UploadParams) {
  const client = getClient(c)
  await client.putObject({
    Body: params.file,
    Bucket: c.env.S3_BUCKET,
    Key: params.key,
    ContentType: params.contentType,
  })
}
function getClient(c: Context) {
  if (s3Client) return s3Client
  const {S3_ACCESS_KEY_ID, S3_SECRET_ACCESS_KEY, S3_ENDPOINT, S3_REGION} = c.env
  s3Client = new S3({
    credentials: {
      accessKeyId: S3_ACCESS_KEY_ID,
      secretAccessKey: S3_SECRET_ACCESS_KEY,
    },
    endpoint: S3_ENDPOINT,
    region: S3_REGION,
  })
  return s3Client
}

QA

上传是如何发起的

为了保护您图片的隐私性,上传行为是由前端发起,因此您可能需要处理跨域问题。

如何避免服务不被滥用

一般情况下,您填入的上传服务接口是公网可访问的,如果接口泄露,这样可能会导致匿名访问甚至滥用。因此,我们建议您使用xid+secret白名单的方式来限制访问。

什么是xid?

xid是figmaId和figmaName的组合字段,格式为figmaName@figmaId。它包含在上传的body当中,您可以在接口中校验这个字段是否在白名单中。

  • figmaName,是Figma登录信息中用户的名字,用户可以在Figma中修改,不是唯一的,但具有可读性。
  • figmaId,19位的数字,是Figma登录信息中用户的唯一标识.

具体可以参阅[Figma User]

xid难以被伪造,已经足够安全,但是如果您需要更高的安全性,我们建议您增加一个secret字段。

什么是secret?

secret是您自己设置的密码,您可以自己生成并颁发给用户,用户在使用插件时需要在Body中填入这个密码。

💡

当然这只是一种建议,具体的安全策略需要根据您的实际情况来制定。

如何排查上传错误

如果您在浏览器中使用Figma,可以在开发者工具中查看Network或Console面板,查看上传的请求和返回。

如果您使用的Figma客户端,您可以按下面提示打开控制台获取错误信息。

如何获取我的xid

在插件首页,点击右上角的用户按钮,您可以看到您的xid。