使用serverless function上传图片

代码

  最近试了试vercel的serverless function,用它实现上传图片到sm.ms图床,选择sm.ms的原因是它原生支持api上传,但不能跨域,所以serverless function的作用是代理api请求,绕过跨域。   serverless function的使用方式很简单,只需在项目根目录下新建一个/api文件夹,在里面写httpHandler就行了,支持多种语言,我这里还是使用Nodejs。创建/api/smms/upload.ts文件如下:

import fs from "fs"; import axios from "axios"; import FormData from "form-data"; import multiparty from "multiparty"; import type { VercelRequest, VercelResponse } from "@vercel/node"; export default async function (req: VercelRequest, res: VercelResponse) { if (req.method.toUpperCase() === "POST") { try { const form = new multiparty.Form(); const data = await new Promise<{fields, files}>((resolve, reject) => { form.parse(req, function (err, fields, files) { if (err) { reject(err); } resolve({ fields, files }); }); }); const token = data.fields.token[0]; const file = data.files.file[0]; const formData = new FormData(); formData.append("smfile", fs.createReadStream(file.path), { knownLength: file.size, filepath: file.path, filename: file.originalFilename }); const len = await new Promise((resolve, reject) => { formData.getLength((err, len) => { if (err) { reject(err); return; } resolve(len); }); }); const response = await axios({ url: "https://sm.ms/api/v2/upload", method: "post", headers: { Authorization: token, "Content-Length": len.toString(), "Content-Type": `multipart/form-data; boundary=${formData.getBoundary()}` }, data: formData }); res.status(response.status).send(response.data); } catch (e) { res.status(503).send(e.toString()); } } else { res.status(405).send("Post only!"); } }

解读

  有三个部分:

  1. 通过multiparty解析req请求,提取到文件。
  2. 把文件构造进FormData
  3. 携带form表单,发送post请求。

  需要注意的是:构造的form表单,文件字段要带上文件信息。header里必须有Content-Length

标签:前端
2年前
0