您的位置:

vue上传文件详解

一、vue上传文件后展示

在介绍vue上传文件的方式之前,我们需要先了解如何在上传文件后展示上传的内容。我们可以借助JavaScript中的FileReader对象来实现。下面的代码片段展示了如何在上传文件后,将其内容展示在页面上:


<template>
  <div>
    <input type="file" @change="previewFile">
    <img :src="imageSrc" v-if="imageSrc">
  </div>
</template>

<script>
export default {
  data() {
    return {
      imageSrc: null
    }
  },
  methods: {
    previewFile(event) {
      const file = event.target.files[0];
      const reader = new FileReader();
      reader.readAsDataURL(file);
      reader.onload = () => {
        this.imageSrc = reader.result;
      };
    }
  }
}
</script>

上面的代码中,我们在模板中添加了一个文件上传框和一个图像标签。选取文件后,调用previewFile函数来处理文件,通过FileReader对象读取图片的URL,并将其绑定到imageSrc变量上,通过v-if指令在页面上展示图片。

二、vue上传文件503

上传文件时,有可能会遇到503错误,表示上传的文件过大或者类型不支持。这时,我们可以在前端代码中设置对应的文件大小和限制文件类型。下面的代码展示了如何在Vue中设置这些限制:


// 在template部分
<div>
  <input type="file" ref="fileInput" @change="handleFileUpload">
</div>

// 在script部分
export default {
  data() {
    return {
      validFileType: ['image/png', 'image/jpg', 'image/jpeg'],
      maxFileSize: 2 * 1024 * 1024 // 最大2MB
    }
  },
  methods: {
    handleFileUpload() {
      const file = this.$refs.fileInput.files[0];
      if (!this.validFileType.includes(file.type)) {
        alert('只能上传jpg/png/jpeg格式的文件!');
        return;
      }
      if (file.size > this.maxFileSize) {
        alert('上传文件大小超过限制!');
        return;
      }
      // 文件通过验证,进行上传操作
    }
  }
}

上面的代码中,我们首先在数据对象中定义了一个数组validFileType和一个数值maxFileSize,分别表示允许上传的文件类型和文件大小限制。handleFileUpload方法中,我们获取到上传的文件,根据文件类型和文件大小进行验证,如果验证通过,则执行上传操作。

三、vue上传文件到后端

在Vue中,我们可以使用axios库进行后端请求。下面的代码片段展示了如何使用axios库,将上传的文件发送到后端:


// 在template部分
<div>
  <input type="file" ref="fileInput" @change="handleFileUpload">
</div>

// 在script部分
import axios from 'axios';

export default {
  methods: {
    handleFileUpload() {
      const file = this.$refs.fileInput.files[0];
      const formData = new FormData();
      formData.append('file', file);
      axios.post('/api/file/upload', formData, {
        headers: {
          'Content-Type': 'multipart/form-data'
        }
      }).then(response => {
        console.log(response);
      }).catch(error => {
        console.log(error);
      });
    }
  }
}

上面的代码中,我们首先导入了axios库。在handleFileUpload方法中,我们先获取上传的文件,创建FormData对象,并将文件添加到其中。然后我们使用axios发起POST请求,将FormData对象作为请求体,同时设置Content-Type为multipart/form-data。上传成功后,控制台会打印出响应结果。

四、vue上传文件到服务器

除了上传到后端,我们也可以将文件上传到服务器存储。服务器端代码可以使用Node.js来实现。下面的代码片段展示了如何使用Node.js和Express框架,将上传的文件保存到服务器上:


const express = require('express');
const fileUpload = require('express-fileupload');
const app = express();

app.use(fileUpload());

app.post('/api/file/upload', (req, res) => {
  const file = req.files.file;
  const fileName = Date.now() + '-' + file.name;
  file.mv(__dirname + '/uploads/' + fileName, error => {
    if (error) {
      console.log(error);
      return res.status(500).send(error);
    }
    res.send('文件上传成功!');
  });
});

app.listen(3000, () => {
  console.log('服务器已启动,监听端口号为3000');
});

上面的代码中,我们首先使用npm安装了express和express-fileupload两个Node.js库。在代码中,我们使用fileUpload中间件来处理上传的文件,然后在/api/file/upload路径上设置了POST方法。在路由处理函数中,我们通过req.files获取到上传的文件,然后生成一个新的文件名,并使用mv方法将文件保存到服务器上。上传成功后,服务器会返回成功信息。

五、vue上传文件进度条

在上传大型文件时,我们可以添加进度条,以使用户了解上传进度。下面的代码片段展示了如何使用axios库和vue-progressbar库来实现上传进度条:


// 在template部分
<div>
  <input type="file" ref="fileInput" @change="handleFileUpload">
  <vue-progress-bar :width="uploadPercentage"></vue-progress-bar>
</div>

// 在script部分
import axios from 'axios';
import VueProgressBar from 'vue-progressbar';

export default {
  components: {
    VueProgressBar
  },
  data() {
    return {
      uploadPercentage: 0
    }
  },
  methods: {
    handleFileUpload() {
      this.uploadPercentage = 0;
      const file = this.$refs.fileInput.files[0];
      const formData = new FormData();
      formData.append('file', file);
      axios.post('/api/file/upload', formData, {
        headers: {
          'Content-Type': 'multipart/form-data'
        },
        onUploadProgress: progressEvent => {
          this.uploadPercentage = parseInt(Math.round((progressEvent.loaded * 100) / progressEvent.total));
        }
      }).then(response => {
        console.log(response);
      }).catch(error => {
        console.log(error);
      });
    }
  }
}

上面的代码中,我们首先导入了VueProgressBar库,然后在模板中添加了一个进度条组件。在数据对象中,我们定义了一个变量uploadPercentage,表示上传进度百分比。在handleFileUpload方法中,我们在发送POST请求时,通过设置onUploadProgress回调函数来更新上传进度。上传结束后,进度条会自动消失。

六、vue上传文件组件

我们可以将文件上传封装成一个Vue组件,使代码更加模块化。下面的代码片段展示了如何实现文件上传组件:


// 在模板部分
<template>
  <div>
    <label :for="id">选择文件</label>
    <input type="file" :id="id" ref="fileInput" style="display: none" @change="handleFileUpload">
    <div v-if="uploadPercentage > 0">
      <vue-progress-bar :width="uploadPercentage"></vue-progress-bar>
    </div>
    <slot></slot>
  </div>
</template>

// 在script部分
import axios from 'axios';
import VueProgressBar from 'vue-progressbar';

export default {
  name: 'FileUpload',
  components: {
    VueProgressBar
  },
  props: {
    id: {
      type: String,
      required: true
    },
    url: {
      type: String,
      required: true
    }
  },
  data() {
    return {
      uploadPercentage: 0
    }
  },
  methods: {
    handleFileUpload() {
      this.uploadPercentage = 0;
      const file = this.$refs.fileInput.files[0];
      const formData = new FormData();
      formData.append('file', file);
      axios.post(this.url, formData, {
        headers: {
          'Content-Type': 'multipart/form-data'
        },
        onUploadProgress: progressEvent => {
          this.uploadPercentage = parseInt(Math.round((progressEvent.loaded * 100) / progressEvent.total));
        }
      }).then(response => {
        this.$emit('uploaded', response.data);
      }).catch(error => {
        console.log(error);
      });
    }
  }
}

上面的代码中,我们将文件上传封装成一个名为FileUpload的组件,在模板中添加了一个input元素,通过props属性传递id和url。在handleFileUpload方法中,我们使用axios库发送POST请求,并通过设置onUploadProgress回调函数来实时更新上传进度。上传完成后,组件通过$emit方法发送uploaded事件,并将响应结果作为参数传递给父组件。

七、vue上传文件夹

在Vue中,我们也可以上传整个文件夹,而不只是单个文件。下面的代码片段展示了如何使用HTML5的webkitdirectory属性来实现上传整个文件夹:


// 在模板部分
<template>
  <div>
    <input type="file" multiple webkitdirectory @change="handleFolderUpload">
  </div>
</template>

// 在script部分
import axios from 'axios';

export default {
  methods: {
    handleFolderUpload() {
      const files = Array.from(event.target.files);
      const formData = new FormData();
      files.forEach(file => {
        formData.append('files[]', file);
      });
      axios.post('/api/folder/upload', formData, {
        headers: {
          'Content-Type': 'multipart/form-data'
        }
      }).then(response => {
        console.log(response);
      }).catch(error => {
        console.log(error);
      });
    }
  }
}

上面的代码中,我们在input元素中添加了multiple和webkitdirectory属性,这样可以支持上传多个文件和整个文件夹。在handleFolderUpload方法中,我们首先通过Array.from方法将文件列表转换为数组,然后使用FormData对象将所有文件添加到其中。通过axios库发送POST请求,将FormData对象作为请求体,上传整个文件夹。

八、vue上传文件打印jason

在Vue中,我们也可以上传一个JSON格式的文件,并在上传成功后打印JSON内容。下面的代码片段展示了如何实现这个功能:


// 在模板部分
<template>
  <div>
    <input type="file" ref="fileInput" @change="handleJsonUpload">
  </div>
</template>

// 在script部分
export default {
  methods: {
    handleJsonUpload() {
      const file = this.$refs.fileInput.files[0];
      const reader = new FileReader();
      reader.readAsText(file);
      reader.onload = event => {
        const json = JSON.parse(event.target.result);
        console.log(json);
      };
    }
  }
}

上面的代码中,我们首先获取上传的文件,然后使用FileReader对象读取文件内容。通过设置onload回调函数,我们将读取到的文件内容转换为JSON对象,并打印到控制台中。

九、Vue上传文件跨域

在开发过程中,为了保证前端代码和后端代码可以分别部署在不同的服务器上,我们需要进行跨域配置。下面的代码片段展示了如何在Vue中配置跨域:


// 在项目的config目录中创建index.js文件
module.exports = {
  dev: {
    proxyTable: {
      '/api': { // 需要跨域的请求路径
        target: 'http://localhost:8080', // 目标服务器地址
        changeOrigin: true, // 改变referer
        pathRewrite: {
          '^/api': '/api' // 替换请求路径
        }
      }
    }