前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >el-upload上传文件

el-upload上传文件

作者头像
赤蓝紫
发布2023-03-16 14:19:01
1.9K0
发布2023-03-16 14:19:01
举报
文章被收录于专栏:clz

el-upload上传文件

前言

公司和学校项目都用到了上传文件的功能,记录一下。

准备

express实现的上传接口

代码语言:javascript
复制
const express = require('express');

// 文件上传模块
const multiparty = require('multiparty')

// 提供跨域资源请求
const cors = require('cors')

// 文件操作
const fs = require('fs')

const app = express();

app.use(cors());

app.get('/policy', (req, res) => {
  res.json({
    code: 200,
    msg: '成功',
    url: '/upload',
    filename: 'clz'
  })
});

app.post('/upload', (req, res) => {
  let form = new multiparty.Form()

  // 配置文件存储路径
  form.uploadDir = './upload'

  form.parse(req, (err, fields, files) => {
    // 解析formData

    for (const file of files.file) {
      const newPath = form.uploadDir + '/' + file.originalFilename

      // renameSync(oldPath, newPath):同步重命名文件,oldPath使用默认上传路径,newPath则是想要保存到的路径
      fs.renameSync(file.path, newPath);
    }

    res.json({
      code: 200,
      msg: '上传成功'
    })
  })
});

app.listen(8088, () => {
  console.log('http://localhost:8088/');
});

如果需要使用,自行查阅express用法,也可以到本人博客中查看简单教程。

开始

简单使用版本

代码语言:javascript
复制
<template>
  <el-upload
    action="http://localhost:8088/upload"
    :show-file-list="true"
    :on-success="handleSuccess"
    :on-error="handleError"
  >
    <el-button type="primary">上传图片</el-button>
  </el-upload>
</template>

<script setup>
import { ElMessage } from "element-plus";

const handleSuccess = (res, file, files) => {
  console.log(res);
  console.log(file, files);

  new ElMessage({
    type: "success",
    message: "上传成功",
  });
};

const handleError = (error, file, files) => {
  console.log(error);
  console.log(file, files);
  ElMessage.error("上传失败");
};
</script>

<style lang="less" scoped>
</style>

解释下上面的属性:

  • action:请求URL
  • show-file-list:是否展文件列表(如果没上传成功,则会闪现一下,再消失)
  • on-success:文件上传成功钩子
    • 参数:
    • res:后端返回的成功响应数据(响应状态为成功时)
    • file:上传的文件
    • files:成功上传的文件列表
  • on-success:文件上传失败钩子
    • 参数:
    • error:错误对象,内容是后端返回的响应数据(响应状态为失败时,如状态码为500)
    • file:上传的文件
    • files:成功上传的文件列表

接下来,去后端设置的路径去看看有没有成功保存上传的文件。

添加token

这个比较简单,因为element-plus也封装好了,只需要使用headers属性,去设置请求头即可

代码语言:javascript
复制
<el-upload
  action="http://localhost:8088/upload"
  :headers="{ token: '12345' }"
>
  <el-button type="primary">上传图片</el-button>
</el-upload>

上传前获取签名再上传

有时候并不是直接上传就可以的,比如一开始并没有上传路径,需要调用获取签名接口来获取上传路径。这个时候就可以使用我们的上传文件之前的钩子before-upload。在上传前调用获取签名的接口,用拿到的url去修改,上传路径,就能够上传了。

代码语言:javascript
复制
<template>
  <el-upload :action="url" :before-upload="getPolicy">
    <el-button type="primary">上传图片</el-button>
  </el-upload>
</template>

<script setup>
import axios from "axios";
import { reactive, ref } from "vue";

const url = ref("");

const getPolicy = () => {
  return new Promise((resolve, reject) => {
    axios
      .get("http://localhost:8088/policy")
      .then((res) => {
        const { data } = res;

        if (data.code === 200) {
          url.value = `http://localhost:8088${data.url}`;

          resolve();
        }
      })
      .catch((error) => {
        reject(error);
      });
  });
};
</script>

<style lang="less" scoped>
</style>

手动上传

我们上面的例子都是选中文件后,就会上传,但是有时候我们会有点击按钮才去上传的需求,这个时候就需要结合auto-uploadsubmit来实现手动上传了。先设置auto-uploadfalse,取消自动上传,这个时候选中图片后就没有上传了,所以我们在按钮的点击事件中,还得使用DOM去调用submit方法去手动上传。

代码语言:javascript
复制
<template>
  <el-upload
    ref="upload"
    action="http://localhost:8088/upload"
    :auto-upload="false"
  >
    <el-button type="primary">上传图片</el-button>
  </el-upload>

  <el-button type="primary" @click="confirm">确定</el-button>
</template>

<script setup>
import { getCurrentInstance } from "vue";

const { proxy } = getCurrentInstance();

const confirm = () => {
  proxy.$refs.upload.submit();
};
</script>

<style lang="less" scoped>
</style>

上传的时候修改文件名

情境:调用签名接口时也给你返回一个文件名,前端在上传的时候需要把文件名改掉再上传,让服务器保存的是规范的文件名。

首先,先说一下结论:无法通过修改File对象的name属性,实现重命名

在上传前钩子中修改File对象的name属性
代码语言:javascript
复制
<template>
  <el-upload
    action="http://localhost:8088/upload"
    :before-upload="getPolicy"
  >
    <el-button type="primary">上传图片</el-button>
  </el-upload>
</template>

<script setup>
// 上传前钩子
const getPolicy = (file) => {
  console.log(file);

  file.name = "clz.png";    // 如果在上传前钩子中对文件的name属性进行修改,则会导致上传不了。而且不报错,难以发现问题所在。

  console.log(file.name);
};
</script>

<style lang="less" scoped>
</style>

毫无波澜。

上传文件时修改

通过http-request属性,覆盖默认的上传行为。

代码语言:javascript
复制
<template>
  <el-upload action="http://localhost:8088/upload" :http-request="httpRequest">
    <el-button type="primary">上传图片</el-button>
  </el-upload>
</template>

<script setup>
const httpRequest = ({ file }) => {
  console.log(file);
  file.name = "clz.png";
};
</script>

<style lang="less" scoped>
</style>

直接报错

解决方案

既然不能直接修改File对象的name属性来实现重命名操作,那么应该怎么办呢?

这个时候就需要通过new File构造函数去再创建一个文件,创建的同时更改名字。

代码语言:javascript
复制
<template>
  <el-upload action="http://localhost:8088/upload" :http-request="httpRequest">
    <el-button type="primary">上传图片</el-button>
  </el-upload>
</template>

<script setup>
const httpRequest = ({ file }) => {
  console.log(file);

  const cloneFile = new File([file], "clz.png");

  console.log(cloneFile);
};
</script>

<style lang="less" scoped>
</style>

注意:如果是更改一个文件的文件名的话,File的构造函数第一个参数应该是包住file的数组

但是这个时候,又有问题了,我们已经使用http-request覆盖默认的上传的行为了,所以我们还得重新实现上传。

上传文件首先需要formData对象,然后给formData添加上数据,在把formData通过接口发出去即可。

代码语言:javascript
复制
<template>
  <el-upload action="#" :http-request="httpRequest">
    <el-button type="primary">上传图片</el-button>
  </el-upload>
</template>

<script setup>
import axios from "axios";
import { ElMessage } from "element-plus";

const httpRequest = ({ file }) => {
  console.log(file);

  const cloneFile = new File([file], "clz.png");

  const formData = new FormData();
  formData.append("file", cloneFile);

  axios.post("http://localhost:8088/upload", formData).then((res) => {
    if (res === 200) {
      new ElMessage({
        type: "success",
        message: "上传成功",
      });
    }
  });
};
</script>

<style lang="less" scoped>
</style>
小贴士

上面已经说出解决方法了,但是,重命名一般不会帮你把文件后缀都给改掉。所以这个时候可以通过正则表达式把后缀给取出来。

代码语言:javascript
复制
const houzhui = file.name.replace(/.+./, "");
const newFile = new File([file], filename+houzhui);

一次请求上传多个文件

el-upload默认一个请求上传一个文件。需要上传多个文件首先得添加multiple属性。

上面的例子中,我们可以发现,我们上面选中了两个文件,点击确定,上传图片时调用了两次上传接口。

既然el-upload默认一个请求上传一个文件,那么我们就不要使用el-upload的上传方法就行了。点击确定按钮时,去调用一个上传文件方法。

因为我们点击确定时,需要获取选中的文件,所以需要有file-list属性,保存选中的文件。

代码语言:javascript
复制
<template>
  <el-upload
    ref="upload"
    action="#"
    multiple
    :file-list="fileList"
    :auto-upload="false"
  >
    <el-button type="primary">上传图片</el-button>
  </el-upload>

  <el-button type="primary" @click="confirm">确定</el-button>
</template>

点击确定按钮,会触发confirm事件,实现一个请求上传多个文件的关键就在这,这个时候创建一个formData对象,遍历选中的文件列表,通过append添加到formData上。最后在调用uploadFile函数,真正把文件上传上去。

代码语言:javascript
复制
const fileList = reactive([]);

const confirm = () => {
  const formData = new FormData();

  console.log(fileList);

  for (const file of fileList) {
    formData.append("file", file.raw);
  }

  uploadFiles(formData);
};

function uploadFiles(data) {
  axios.post("http://localhost:8088/upload", data).then((res) => {
    if (res === 200) {
      new ElMessage({
        type: "success",
        message: "上传成功",
      });
    }
  });
}

小技能

获取图片的宽高像素

代码语言:javascript
复制
// 创建Image对象
const img = new Image();

// 设置图片的src
img.src = 'https://www.clzczh.top/medias/featureimages/19.png';

// 添加load事件,图片加载完成后执行
img.onload = () => {
  // 获取图片的宽高像素
  console.log(img.width, img.height);
};
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-05-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • el-upload上传文件
    • 前言
      • 准备
        • express实现的上传接口
      • 开始
        • 简单使用版本
        • 添加token
        • 上传前获取签名再上传
        • 手动上传
        • 上传的时候修改文件名
        • 一次请求上传多个文件
      • 小技能
        • 获取图片的宽高像素
    相关产品与服务
    文件存储
    文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档