代码 最近试了试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!"); } }解读 有三个部分: 通过multiparty解析req请求,提取到文件。 把文件构造进FormData。 携带form表单,发送post请求。 需要注意的是:构造的form表单,文件字段要带上文件信息。header里必须有Content-Length。
使用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!"); } }
解读
有三个部分:
multiparty
解析req请求,提取到文件。FormData
。需要注意的是:构造的form表单,文件字段要带上文件信息。header里必须有Content-Length。