本篇博客适合了解vue项目、了解eggjs、了解axios的小伙伴阅读,如果不是熟悉这些技术,可以先去看看相关视频或者网站学习。
一份表单中包含有普通参数、也有要上传的文件,将这些数据放到formdata中传递到后端进行处理。 我这里的前端用的是vue2,页面仅有一个表单,页面的代码如下:
<template>
<div class="about">
<el-form :model="form"
status-icon
label-width="100px"
class="demo-ruleForm">
<el-form-item label="内容"
prop="content">
<el-input type="text"
v-model="form.content"
autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="文件"
prop="audio">
<el-upload class="avatar-uploader"
action=""
:show-file-list="false"
:before-upload="beforeUpload"
:on-change="change">
上传
</el-upload>
<audio :src="audioSrc"
controls="controls" />
<div>{{filename}}</div>
</el-form-item>
<el-form-item>
<el-button type="primary"
@click="submitForm">提交</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
import $api from "../utils/api";
export default {
data: () => {
return {
filename: "",
form: { content: "" },
fileBase64: "",
audioSrc: "",
formdata: new FormData(),
};
},
watch: {},
mounted() {},
methods: {
change(file) {
console.log(file);
const isMp3 = file.raw.type === "audio/mpeg";
if (!isMp3) {
return 0;
} else {
this.formdata.append("upfile", file.raw);
this.formdata.append("filename", file.raw.name);
this.filename = file.raw.name;
this.base64_encode(file.raw);
}
},
base64_encode(file) {
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
this.fileBase64 = reader.result;
let audioBlob = this.base64ToBlob(this.fileBase64, "mp3");
this.audioSrc = window.URL.createObjectURL(audioBlob);
};
},
base64ToBlob(base64, type) {
let arr = base64.split(",");
let array = arr[0].match(/:(.*?);/);
let mime = (array && array.length > 1 ? array[1] : type) || type;
let bytes = window.atob(arr[1]);
let abuffer = new ArrayBuffer(bytes.length);
let u8a = new Uint8Array(abuffer);
for (let i = 0; i < bytes.length; i++) {
u8a[i] = bytes.charCodeAt(i);
}
return new Blob([abuffer], {
type: mime,
});
},
beforeUpload(file) {
const isMp3 = file.type === "audio/mpeg";
if (!isMp3) {
this.$message.error("上传头像图片只能是 mp3 格式!");
}
return false;
},
submitForm() {
this.formdata.append("content", this.form.content);
$api
.post("/audio", this.formdata)
.then((res) => {
console.log(res);
if (res.data.status == 1) {
this.$message({
message: "提交成功",
duration: 1000,
type: "success",
});
this.formdata = new FormData();
} else {
this.$message({
message: "提交失败",
duration: 1000,
type: "error",
});
}
})
.catch((e) => {
console.log(e);
});
},
},
};
</script>
前端使用的是axios来发起请求,因为我们使用FormData传递文件数据,所以需要设置请求头中的content-type为 “multipart/form-data”
import axios from "axios";
const $api = axios.create({ baseURL: "http://127.0.0.1:7001" })
$api.interceptors.request.use(function (config) {
config.headers['content-type'] = "multipart/form-data";
return config;
}, function (error) {
return Promise.reject(error);
});
export default $api;
egg后端代码,先在config.default.js中设置multipart,这里的设置官网有,但是官网只写了mode:“file”,我使用的时候,系统会报错。 这里设置一下文件大小,我设置到100mb大,可以上传小于100mb的文件。 文件类型我只做了MP3的例子,根据需要修改。
config.multipart = {
fileSize: '100mb',
mode: 'stream',
fileExtensions: ['.mp3'],
};
router.js文件中设置接口路由
'use strict';
module.exports = app => {
const { router, controller } = app;
router.post('/audio', controller.home.uploadAudio);
};
控制器中写入uploadAudio方法,egg需要安装await-stream-ready、stream-wormhole、formidable插件
'use strict';
const Controller = require('egg').Controller;
const fs = require('fs');
const path = require('path');
const awaitWriteStream = require('await-stream-ready').write;
const sendToWormhole = require('stream-wormhole');
const audioBaseUrl = 'app/public/audio';
const formidable = require("formidable");
class HomeController extends Controller {
async uploadAudio() {
const { ctx } = this;
try {
function parse(req) {
const form = new formidable.IncomingForm();
return new Promise((resolve, reject) => {
form.parse(req, (err, fields, files) => {
resolve({ fields, files });
reject((res) => { console.log(res) })
});
});
}
const extraParams = await parse(this.ctx.req);
console.log("FormData中的普通参数-----------", extraParams.fields);
console.log("FormData中的文件--------------", extraParams.files);
const file = extraParams.files.upfile;
const stream = fs.createReadStream(file._writeStream.path);
const fileName = extraParams.fields.filename;
const target = path.join(audioBaseUrl, fileName);
const writeStream = fs.createWriteStream(target);
try {
await awaitWriteStream(stream.pipe(writeStream));
} catch (err) {
await sendToWormhole(stream);
console.log(err)
}
ctx.body = { status: 1 }
} catch (err) {
console.log(err)
ctx.body = { status: 0 }
}
}
}
module.exports = HomeController;
页面显示如下: 点击“上传”,即可选择文件,选好MP3文件后,页面可以进行播放。 egg中就可以打印出这些信息了: 并且将音频文件存入到指定的目录中
|