nodejs+axios实现服务端文件上传

2023-10-19 后端开发 0

最近有一个发送图文消息,需要上传图片到临时素材库。之前做过文件上传到阿里云、七牛云都是服务端提供封装好的文件上传接口,在客户端使用ajax的方式上传。所以就来踩踩坑,使用nodejs+axios实现服务端文件上传。

一、接口文档介绍

请求方式:POST(HTTPS)
请求地址:https://qyapi.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE

  • 使用multipart/form-dataPOST上传文件, 文件标识名为”media”。

  • POST的请求包中,form-data中媒体文件标识,应包含有 filename、filelength、content-type等信息。

  • 参数说明:

参数必须说明
access_token调用接口凭证
type媒体文件类型,分别有图片(image)、语音(voice)、视频(video),普通文件(file)

二、文件上传

2-1.初始化项目

# 创建目录
mkdir upload-demo

# 进入upload-demo目录
cd upload-demo

# npm 初始化
npm init -y

# 创建app.js
touch app.js

2-2.安装插件依赖

  • axios:是一个基于 promiseHTTP库,可以用在客户端浏览器和服务端node.js中。

  • form-data:是创建可读multipart/form-data流的库。可用于向其他 Web 应用程序提交表单和文件上传。

npm i -S axios form-data

2-3.上传核心代码

// app.jsconst fs = require('fs')const FormData = require('form-data')const axios = require('axios');(async ()=>{
    let formData = new FormData();
    let imgFiles = fs.createReadStream('./test.jpg')    // 根目录下需要有一个test.jpg文件
    formData.append('media', imgFiles);
    let len = await new Promise((resolve, reject) => {
      return formData.getLength((err, length) => (err ? reject(err) : resolve(length)));
    });
    axios({
        url: 'https://qyapi.weixin.qq.com/cgi-bin/media/upload',
        method: 'POST',
        params: {
            access_token: 'ACCESS_TOKEN',   // ACCESS_TOKEN 需要替换为真实 token
            type: 'image',   // 这里以上图片为例
        },
        data: formData,
        headers: {
          ...formData.getHeaders(), // 小心
          'Content-Length': len,    // 谨慎
        },
    }).then(res=>{
        console.log(res.data)
    })})();

注意:headers中需要设置 Content-TypeContent-Length,不然会出现类似 Request failed with status code 412statusCode: 412, statusMessage: Precondition Failed这种报错。

PS:
HTTP 412错误 (Precondition failed),是HTTP协议状态码的一种,表示"未满足前提条件"。如果服务器没有满足请求者在请求中设置的其中一个前提条件时就会返回此错误代码。
412错误一般是由于要查看的网页设置了先决条件,一般是网页中有一个或多个请求标题字段中具有先决条件,这些字段经服务器测试后被认为是"FALSE"。客户端为当前资源的 meta信息(头文件字段数据)设置了先决条件,以便防止请求的方法被用于指定资源外的其他资源,因此该请求无法完成而出现的错误。

2-4.执行脚本

node app.js

不出意外会输入以下内容

{
   "errcode": 0,
   "errmsg": "",   "type": "image",
   "media_id": "1G6nrLmr5EC3MMb_-zK1dDdzmd0p7cNliYu9V5w7o8K0",
   "created_at": "1380000000"
}

其中media_id就是上传到素材库的媒体文件唯一标识,发送图文消息时需要用到。