vue+elementui+minio实现前端直接上传文件到minio服务端存储
呈现如下图:
在这里插入图片描述

实现方法

<template>
  <div class="minioBox">
    <el-button style="marginRight:10px;" @click="getFileName" size="mini" type="success">选择文件</el-button>
    <input type="file" multiple="multiple" id="minIoFile" ref="minIoFile" v-show="false" @change="getFile">
    <el-button v-if="fileList.length>0" style="marginRight:10px;" @click="upload" size="mini" type="success">上传</el-button>
    <ul class="uploadFileList">
      <li v-for="item,index of fileList" :key="index">
        <span class="subString">{{item.name}}</span>&nbsp;
        <span>({{(item.size/1024/1024).toFixed(5)}}M)</span>
        <div class="floatRight" style="float: right;">
          <i class="el-icon-close" style="cursor: pointer;" @click="deleteMinioFile(index)"></i>
        </div>
      </li>
    </ul>
    <ul>
      <li v-for="item,index of urlList" :key="index">
        <span @click="downLoad(item.url,item.name)">{{item.name}}-----</span>
      </li>
    </ul>
  </div>
</template>
<script>

let Minio = require('minio')
let stream = require('stream')
//连接minio文件服务器
var minioClient = new Minio.Client({
    endPoint: '***',   //对象存储服务的URL
    port: 9000,//端口号
    useSSL: false,   //true代表使用HTTPS
    accessKey: '***',   //账户id
    secretKey: '***',   //密码
    partSize: '50M'
});
//上边这块需要注意,放上minio的账号密码,存储服务器url(容易出错,格式如192.168.5.30,不要多写),以及端口号
export default {
  data(){
    return{
      fileList:[],
      urlList:[]
    }
  },
  methods: {
     downLoad(filename,names){//下载模板

      var x=new XMLHttpRequest();
      var resourceUrl = filename
      x.open("GET", resourceUrl, true);
      x.responseType = 'blob';
      x.onload=function(e){
        // ie10+
        if (navigator.msSaveBlob) {
          var name = resourceUrl.substr(resourceUrl.lastIndexOf("/") + 1);
          return navigator.msSaveBlob(x.response, name);
        } else {
          var url = window.URL.createObjectURL(x.response)
          var a = document.createElement('a');
          a.href = url;
          a.download = names;
          a.click();
        }
      }
      x.send();

    },
    upload(){
      console.log(this.fileList);
      this.fileList.map((item,index) => {
        console.log(item);
        this.uploadMinIo(item,index);
      })
      // console.log(this.fileList);
    },
    deleteMinioFile(index){
      this.fileList.splice(index,1)
    },
    getFileName(){
      let inputDOM = this.$refs.minIoFile;
      inputDOM.click();
    },
    getFile(event){
      console.log(event);
      console.log(document.getElementById('minIoFile').files);
      let files = document.getElementById('minIoFile').files;
      let arr = [];
      let fileSwitch = true;
      if(files.length > 0){
        for(let i = 0;i<files.length;i++){
          if((files[i].size/1024/1024).toFixed(5)>64){
            this.$message({
              message: `${item.name}超过文件的最大长度`,
              type: 'warning'
            });
            fileSwitch = false;
          }
        }
        if(fileSwitch){

          for(let i = 0;i<files.length;i++){
            console.log(files[i]);
             if((files[i].type=='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') 
             || (files[i].type == 'application/vnd.ms-excel')
             || (files[i].type == 'text/plain')
             || (files[i].type == 'image/png')
             || (files[i].type == 'image/gif')
             || (files[i].type == 'image/jpg')
             || (files[i].type == 'application/vnd.openxmlformats-officedocument.wordprocessingml.document')
             || (files[i].type == 'application/vnd.openxmlformats-officedocument.presentationml.presentation')
             ){
              this.fileList.push(files[i])
             }else{
               console.log("类型不对");
             }
           
          }
          console.log(this.fileList);
        }
      }
    },
    //上传文件
    uploadMinIo(fileObj,index) {
     this.fileList=this.fileList.filter((self,el)=>{
       return self != fileObj
     })
      let vm = this
      // const files = fileObj;
      if (fileObj) {
        let file = fileObj
        //判断是否选择了文件
        if (file == undefined) {
          //未选择
          console.log("请上传文件")
        } else {
          //选择
          //获取文件类型及大小
          const fileName = file.name
          const mineType = file.type
          const fileSize = file.size

          //参数
          let metadata = {
            "content-type": mineType,
            "content-length": fileSize
          }
          //判断储存桶是否存在
          minioClient.bucketExists('filesmore', function(err) {
            if (err) {
              if (err.code == 'NoSuchBucket') return console.log("bucket does not exist.")
              return console.log(err)
            }
            //存在
            console.log('Bucket exists.')
            //准备上传
            let reader = new FileReader();
            reader.readAsDataURL(file);
            reader.onloadend = function (e) {//读取完成触发,无论成功或失败
              console.log(e);
              const dataurl = e.target.result
              //base64转blob
              const blob = vm.toBlob(dataurl)
              //blob转arrayBuffer
              let reader2 = new FileReader()
              reader2.readAsArrayBuffer(blob)

              reader2.onload = function(ex) {
                //定义流
                let bufferStream = new stream.PassThrough();
                //将buffer写入
                bufferStream.end(new Buffer(ex.target.result));
                //上传
                minioClient.putObject('filesmore', fileName, bufferStream, fileSize, metadata, function(err, etag) {
                  console.log(etag);
                  if (err == null) {
                    minioClient.presignedGetObject('filesmore', fileName, 24*60*60, function(err, presignedUrl) {
                      if (err) return console.log(err)
                      //输出url
                      console.log(presignedUrl)
                      var only = {url:presignedUrl,name:fileName}
                      console.log(only);
                      vm.urlList.push(only)
                      // window.open(presignedUrl)
                      // this.$notify({
                      //   title: '标题名称',
                      //   message: h('i', { style: 'color: teal'}, '这是提示文案这是提示文案这是提示文案这是提示文案这是提示文案这是提示文案这是提示文案这是提示文案')
                      // });
                    })
                  }
                  //return console.log(err, etag)
                })
              }
            }
          })
        }

      }
    },
    //base64转blob
    toBlob (base64Data) {
      let byteString = base64Data
      if (base64Data.split(',')[0].indexOf('base64') >= 0) {
        byteString = atob(base64Data.split(',')[1]) // base64 解码
      } else {
        byteString = unescape(base64Data.split(',')[1])
      }
      // 获取文件类型
      let mimeString = base64Data.split(';')[0].split(":")[1] // mime类型

      // ArrayBuffer 对象用来表示通用的、固定长度的原始二进制数据缓冲区
      // let arrayBuffer = new ArrayBuffer(byteString.length) // 创建缓冲数组
      // let uintArr = new Uint8Array(arrayBuffer) // 创建视图

      let uintArr = new Uint8Array(byteString.length) // 创建视图

      for (let i = 0; i < byteString.length; i++) {
        uintArr[i] = byteString.charCodeAt(i)
      }
      // 生成blob
      const blob = new Blob([uintArr], {
        type: mimeString
      })
      // 使用 Blob 创建一个指向类型化数组的URL, URL.createObjectURL是new Blob文件的方法,可以生成一个普通的url,可以直接使用,比如用在img.src上
      return blob
    }
  }
}
</script>
<style lang="scss" scoped>
.minioBox{
  color: #000000;
  padding: 10px;
  width: 90%;
  .uploadFileList {
    width: 100%;
    li {
      height: 22px;
      line-height: 22px;
      margin: 10px 0px;
      span {
        margin-right: 10px;
        vertical-align: top;
      }
      .subString {
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        width: 53%;
        display: inline-block;
      }
      i {
        margin: 5px 5px 0 0;
      }
      .el-icon-close,
      .el-icon-upload-success {
        float: right;
      }
      .upload-success {
        color: green;
      }
      .upload-fail {
        color: red;
      }
    }
    li:hover {
      background-color: #f5f7fa;
    }
    li:first-child {
      margin-top: 10px;
    }
    /deep/ .progress {
      margin-top: 2px;
      width: 200px;
      height: 14px;
      margin-bottom: 10px;
      overflow: hidden;
      background-color: #f5f5f5;
      border-radius: 4px;
      -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
      box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
      display: inline-block;
      .progress-bar {
        background-color: rgb(92, 184, 92);
        background-image: linear-gradient(
          45deg,
          rgba(255, 255, 255, 0.14902) 25%,
          transparent 25%,
          transparent 50%,
          rgba(255, 255, 255, 0.14902) 50%,
          rgba(255, 255, 255, 0.14902) 75%,
          transparent 75%,
          transparent
        );
        background-size: 40px 40px;
        box-shadow: rgba(0, 0, 0, 0.14902) 0px -1px 0px 0px inset;
        box-sizing: border-box;
        color: rgb(255, 255, 255);
        display: block;
        float: left;
        font-size: 12px;
        height: 20px;
        line-height: 20px;
        text-align: center;
        transition-delay: 0s;
        transition-duration: 0.6s;
        transition-property: width;
        transition-timing-function: ease;
        width: 266.188px;
      }
    }
  }
}
</style>

需要安装插件如下:
npm install node-sass --save-dev //安装node-sass
npm install sass-loader --save-dev //安装sass-loader
npm install style-loader --save-dev //安装style-loader
npm install --save minio
npm install --save stream
尤其是sass容易报错,可能是版本问题导致,我使用的版本是
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

GitHub 加速计划 / eleme / element
54.06 K
14.63 K
下载
A Vue.js 2.0 UI Toolkit for Web
最近提交(Master分支:2 个月前 )
c345bb45 6 个月前
a07f3a59 * Update transition.md * Update table.md * Update transition.md * Update table.md * Update transition.md * Update table.md * Update table.md * Update transition.md * Update popover.md 7 个月前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐