目标:将 [前端 → 后端] 改成 [前端 → 中间层 → 后端]
第一步:自定义上传行为(ElementPlus)
<template>
<el-upload
action=""
show-file-list
v-model:file-list="fileList"
:on-change="handleChange"
:on-success="handleSuccess"
:on-error="handleError"
:http-request="httpRequest"
>
<el-button type="primary">Click to upload</el-button>
</el-upload>
</template>
<script setup>
import { ref } from 'vue';
const fileList = ref([]);
const handleChange = () => {
fileList.value = fileList.value.slice(-1);
};
const httpRequest = async (item) => {
const formData = new FormData();
formData.append('data', item.file);
formData.append('type', 'cdoShelf');
const res = await fetch('http://127.0.0.1:8360/upload', {
method: 'POST',
body: formData,
});
console.log('[res]:', res);
};
const handleSuccess = (...args) => {
console.log('handleSuccess', args);
};
const handleError = (...args) => {
console.log('handleError', args);
};
</script>
要点 1:使用 http-request 自定义 el-upload 的上传行为
要点 2:POST 请求的数据格式为 FormData
要点 3:文件以 File 对象的形式传递
第二步:中间层转发(ThinkJS)
const axios = require('axios');
const fs = require('fs');
const FormData = require('form-data');
module.exports = class extends think.Controller {
async postAction() {
const data = this.post(); // 获取 body 参数
const file = this.file(); // 获取文件
console.log('[data]:', data);
console.log('[file]:', file);
const formData = new FormData();
formData.append('file', fs.createReadStream(file.data.path));
formData.append('type', data.type);
const res = await axios({
method: 'post',
url: '后端的上传接口',
data: formData,
})
.then(function (response) {
think.logger.info('response-data', response.data);
return response.data;
})
.catch(function (error) {
think.logger.error('error', error);
return Promise.reject(error);
});
console.log('[res]:', res);
}
};
要点 1:Node 中没有 Fetch API,需要使用第三方库(上例为 Axios)发起请求
要点 2:POST 请求的数据格式为 FormData
要点 3:Node 中没有 File 对象,需要通过 fs 模块创建 Stream 对象来传递文件