- 单文件上传 前端
<template>
<div>
<Button type="primary" @click="click">{{BtnText}}</Button>
<input
type="file"
@change="picUpload($event)"
style="display:none;"
ref="fileid"
accept="image/*"
/>
</div>
</template>
<script>
import { ImageZip } from "../../utils/tools.js";
export default {
name: "UploadPhotoBtn",
props: {
uploadParam: {
type: Object
}
},
data() {
return {
BtnText: "图片上传"
};
},
watch: {
UploadPhotoBtn: {
handler() {
if (this.uploadParam.Text) {
this.BtnText = this.uploadParam.Text;
}
},
immediate: true
}
},
methods: {
//1.获取上传图片
picUpload(event) {
const self = this;
let files = event.target.files[0];
//图片压缩
ImageZip(files, function(baseData) {
self.upLoads(baseData);
});
},
//2.上传图片
async upLoads(baseData) {
const self = this;
let formData = new FormData();
formData.append("FileType", this.uploadParam.FileType);
formData.append("file", baseData.blobUrl);
const res = await this.$curl.post("api/ydy/uploadFile", formData);
this.$refs.fileid.value = ""; //上传成功后,清除file值,防止相同图片无法上传。
//3.上传成功后,结果回调给父组件
this.$emit("uploadCallback", res);
},
//点击上传
click() {
this.$refs.fileid.dispatchEvent(new MouseEvent("click")); //触发file方法
}
}
};
</script>
后端
async uploadFile(){
try{
//1.获取文件流
const stream = await this.ctx.getFileStream();
let baseDir = this.config.FileDir; //保存的路径
//2.获取文件后缀类型
const fileExt = stream.filename.substr(stream.filename.lastIndexOf("."));
let FileType = stream.fields.FileType;//业务文件类型
let tag = stream.fields.tag;//tag
// 文件大小
let size = stream._readableState && stream._readableState.length ? stream._readableState.length : 0;
size = this.formatBytes(size);
let YearMonth = moment().format("YYYYMM");
let YearMonthDay = moment().format("YYYYMMDD");
if(!FileType){
FileType="AllFile";
};
//3.保存的文件名称:格式为yyyyMMddhhmmss_随机4位数_FileType
let FileName = moment().format("YYYYMMDDHHmmss") + "_" + Math.floor(Math.random() * 10000 + 1000) + "_" + FileType + fileExt;
let FilePath =FileType+"/"+YearMonth+"/"+YearMonthDay+"/";
//4.创建文件保存的路径
const url = path.join(baseDir, FilePath);
if(!fs.existsSync(url)){
url.split(path.sep).reduce((currentPath, folder) => {
currentPath += folder + path.sep;
if (!fs.existsSync(currentPath)) {
fs.mkdirSync(currentPath);
}
return currentPath;
}, "");
};
//4.文件保存
const savepath = path.join(url, FileName);
const writeStream = fs.createWriteStream(savepath);
await awaitWriteStream(stream.pipe(writeStream));
let videoList = [".mp4",".mov",".wmv",".flv",".avi",".avchd",".webm",".mkv"];
if(videoList.includes(fileExt)){
let videoPath = FilePath+FileName;
await this.getVideoPhoto(videoPath);
}
return {
state:1,
tag: tag||null,
FilePath: FilePath+FileName,
SaveName: FileName,
FileName: stream.filename,
videoPhoto: FilePath+FileName.substr(0,FileName.lastIndexOf("."))+".jpg",
url: '/'+FilePath+FileName,
filePath: '/'+FilePath+FileName,
size: size,
FileType
}
}catch(error){
console.log(error)
// return { state:0,msg:"文件上传失败",error:error.toString()}
return { state:0};
}
}
- 多文件上传-单文件传递后端
<template>
<!-- 多文件上传-单文件传递后端 -->
<div>
<Upload style="height:32px" action ref="file" multiple accept=".jpg,.jpeg,.png" :format="[ 'jpg', 'jpeg','png']" :before-upload="handleUpload">
<Button>上传图片</Button>
</Upload>
</div>
</template>
<script>
import { ImageZip } from "../../utils/tools.js";
export default {
name: "uploadMultiple",
props: {
uploadParam: {
type: Object
}
},
data(){
return{
file:null
}
},
methods:{
handleUpload(file) {
this.file = file;
//图片压缩
const self=this;
ImageZip(this.file, function(baseData) {
self.uploadExcel(baseData);
});
return false;
},
async uploadExcel(baseData) {
let formData = new FormData();
formData.append("FileType", this.uploadParam.FileType);
formData.append("file",baseData.blobUrl);
let res = await this.$curl.post(
"api/ydy/uploadFile",
formData
);
//3.上传成功后,结果回调给父组件
this.$emit("uploadCallback", res);
},
},
mounted(){
}
}
</script>
<style lang="scss" scoped>
</style>
后端
async uploadFile(){
try{
//1.获取文件流
const stream = await this.ctx.getFileStream();
let baseDir = this.config.FileDir; //保存的路径
//2.获取文件后缀类型
const fileExt = stream.filename.substr(stream.filename.lastIndexOf("."));
let FileType = stream.fields.FileType;//业务文件类型
let tag = stream.fields.tag;//tag
// 文件大小
let size = stream._readableState && stream._readableState.length ? stream._readableState.length : 0;
size = this.formatBytes(size);
let YearMonth = moment().format("YYYYMM");
let YearMonthDay = moment().format("YYYYMMDD");
if(!FileType){
FileType="AllFile";
};
//3.保存的文件名称:格式为yyyyMMddhhmmss_随机4位数_FileType
let FileName = moment().format("YYYYMMDDHHmmss") + "_" + Math.floor(Math.random() * 10000 + 1000) + "_" + FileType + fileExt;
let FilePath =FileType+"/"+YearMonth+"/"+YearMonthDay+"/";
//4.创建文件保存的路径
const url = path.join(baseDir, FilePath);
if(!fs.existsSync(url)){
url.split(path.sep).reduce((currentPath, folder) => {
currentPath += folder + path.sep;
if (!fs.existsSync(currentPath)) {
fs.mkdirSync(currentPath);
}
return currentPath;
}, "");
};
//4.文件保存
const savepath = path.join(url, FileName);
const writeStream = fs.createWriteStream(savepath);
await awaitWriteStream(stream.pipe(writeStream));
let videoList = [".mp4",".mov",".wmv",".flv",".avi",".avchd",".webm",".mkv"];
if(videoList.includes(fileExt)){
let videoPath = FilePath+FileName;
await this.getVideoPhoto(videoPath);
}
return {
state:1,
tag: tag||null,
FilePath: FilePath+FileName,
SaveName: FileName,
FileName: stream.filename,
videoPhoto: FilePath+FileName.substr(0,FileName.lastIndexOf("."))+".jpg",
url: '/'+FilePath+FileName,
filePath: '/'+FilePath+FileName,
size: size,
FileType
}
}catch(error){
console.log(error)
// return { state:0,msg:"文件上传失败",error:error.toString()}
return { state:0};
}
}
3.多文件上传-多文件传递后端
<template>
<!-- 多文件上传-多文件传递后端 -->
<div>
<Button type="primary" @click="click">上传</Button>
<input
type="file"
multiple="multiple"
@change="picUpload($event)"
style="display:none;"
ref="fileid"
accept="image/*"
/>
</div>
</template>
<script>
export default {
name: "uploadMultiple",
props: {
uploadParam: {
type: Object
}
},
data(){
return{
file:null
}
},
methods:{
//点击上传
click() {
this.$refs.fileid.dispatchEvent(new MouseEvent("click")); //触发file方法
},
async picUpload(event){
const files = event.target.files;
let formData = new FormData();
formData.append("FileType", this.uploadParam.FileType);
for (let i = 0; i < files.length; i++) {
const file = files[i];
// 这里可以添加上传逻辑,例如使用FormData上传
formData.append(`file`, file);
}
let res = await this.$curl.post("/api/ydy/uploadMultipleFile", formData, {
Headers: { "Content-Type": "multipart/form-data" }
});
},
async uploadExcel() {
let formData = new FormData();
formData.append("file", this.file);
let res = await this.$curl.post("/api/ydy/uploadMultipleFile", formData, {
Headers: { "Content-Type": "multipart/form-data" }
});
if (res.ok && res.requireMsg) {
this.$Message.warning(`${res.requireMsg}`);
return
}
if (res.ok) {
this.getTableData();
this.$Message.success("导入成功!!!");
}
},
},
mounted(){
}
}
</script>
<style lang="scss" scoped>
</style>
后端
async uploadMultipleFile(){
try{
const {ctx} = this
let baseDir = this.config.FileDir; //保存的路径
// 获取多个文件提交的数据流,多文件上传专用
const parts =await ctx.multipart({ autoFields:true });
let YearMonth = moment().format("YYYYMM");
let YearMonthDay = moment().format("YYYYMMDD");
const files = [];
let stream
while( ( stream = await parts() ) != null )
{
// 判断用户是否选择上传图片
if (!stream.filename)
{
ctx.throw('请选择上传的图片!')
return
}
let FileType=await parts.field;
if(!FileType){
FileType="AllFile";
};
// filename 获取上传的文件名 xxx.jpg
const filename = stream.filename.toLowerCase()
// fieldname 获取文件表单提交的字段名称
const fieldname = stream.fieldname
const fileExt =filename.substr(filename.lastIndexOf("."));
//3.保存的文件名称:格式为yyyyMMddhhmmss_随机4位数_FileType
let FileName = moment().format("YYYYMMDDHHmmss") + "_" + Math.floor(Math.random() * 10000 + 1000) + "_" + FileType + fileExt;
let FilePath =FileType+"/"+YearMonth+"/"+YearMonthDay+"/";
//4.创建文件保存的路径
const url = path.join(baseDir, FilePath);
if(!fs.existsSync(url)){
url.split(path.sep).reduce((currentPath, folder) => {
currentPath += folder + path.sep;
if (!fs.existsSync(currentPath)) {
fs.mkdirSync(currentPath);
}
return currentPath;
}, "");
};
//4.文件保存
const savepath = path.join(url, FileName);
// 创建可写流
const writeStream = fs.createWriteStream(savepath)
// 读取文件 && 写入 && 销毁当前流
await pump(stream, writeStream)
files.push({
[fieldname]: '/'+FilePath+FileName
})
}
return {
files,
fields:parts.field
}
}catch(error){
console.log(error)
return{
}
}
}
调用方法
<uploadMultiple2 :uploadParam="uploadPhotoParam" @uploadCallback="uploadCallback($event)" v-show="uploadPic"></uploadMultiple2>
传递参数
fileParam: {
FileType: "checkStation",
},