我是靠谱客的博主 苗条电话,最近开发中收集的这篇文章主要介绍Vue封装基于ajax和fetch两种方式上传文件组件完整代码,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

参考:https://www.php.cn/js-tutorial-395168.html以及element-ui的图片上传源码。图片上传虽然是多选,但是实际上传图片上传的时候 仍然是一张一个一张一个请求上传的。

1. 新建axios.js文件,实现ajax文件上传:

//新建axios.js文件,实现ajax文件上传
export default function sendRequest(option) {
  upload(option);
}
function upload(option) {
  if (typeof XMLHttpRequest === 'undefined') {
    return;
  }

  const xhr = new XMLHttpRequest();
  const action = option.action;

  if (xhr.upload) {
    xhr.upload.onprogress = function progress(e) {
      if (e.total > 0) {
        e.percent = e.loaded / e.total * 100;
      }
      option.onProgress(e);
    };
  }

  const formData = new FormData();

  if (option.data) {
    Object.keys(option.data).forEach(key => {
      formData.append(key, option.data[key]);
    });
  }

  formData.append(option.filename, option.file, option.file.name);

  xhr.onerror = function error(e) {
    option.onError(e);
  };

  xhr.onload = function onload() {
    if (xhr.status < 200 || xhr.status >= 300) {
      return option.onError(getError(action, option, xhr));
    }

    option.onSuccess(getBody(xhr));
  };

  xhr.open('post', action, true);

  if (option.withCredentials && 'withCredentials' in xhr) {
    xhr.withCredentials = true;
  }

  const headers = option.headers || {};

  for (let item in headers) {
    if (headers.hasOwnProperty(item) && headers[item] !== null) {
      xhr.setRequestHeader(item, headers[item]);
    }
  }
  xhr.send(formData);
  return xhr;
}
function getError(action, option, xhr) {
  var msg = void 0;
  if (xhr.response) {
    msg = xhr.status + ' ' + (xhr.response.error || xhr.response);
  } else if (xhr.responseText) {
    msg = xhr.status + ' ' + xhr.responseText;
  } else {
    msg = 'fail to post ' + action + ' ' + xhr.status;
  }
  var err = new Error(msg);
  err.status = xhr.status;
  err.method = 'post';
  err.url = action;
  return err;
}

function getBody(xhr) {
  var text = xhr.responseText || xhr.response;
  if (!text) {
    return text;
  }
  try {
    return JSON.parse(text);
  } catch (e) {
    return text;
  }
}

2. vue封装自己的图片上传组件myUpload.vue:

<template>
  <div class="my_upload">
    <input
      style="display:none"
      @change="inputChange"
      :multiple="multiple"
      type="file"
      :name="name"
      id="upload"
      ref="uploadInput"
    />
  </div>
</template>
<script>
import sendRequest from "./axios.js"
export default {
  name: "my_upload",
  props: {
    multiple: {//是否多选
      type: Boolean,
      default: true
    },
    name: {//文件名字
      type: String,
      default: "file"
    },
    action: {  //图片上传路径
      type: String,
      default: "",
      require: true
    },
    data:{  //图片上传参数
        type:Object,
        default:()=>({})
    },
    headers:{ //请求头
        type:Object,
        default:()=>({})
    },
  },
  methods: {
    inputChange(ev) {
      const files = ev.target.files;
      if (!files) return;
      this.uploadFiles(files);
    },
    uploadFiles(files) {
      let postFiles = Array.prototype.slice.call(files); //因为files是具有length属性的对象,Array.prototype.slice.call(arguments)能将具有length属性的对象(key值为数字)转成数组。
      //如var obj = {0:'hello',1:'world',length:2};console.log(Array.prototype.slice.call(obj,0));输出为["hello", "world"]
      if (!this.multiple) { //非多选情况下,取第一个
        postFiles = postFiles.slice(0, 1);
      } 
      if (postFiles.length === 0) { //没有就不在向下执行
        return;
      } 
      postFiles.forEach(rawFile => {
        this.upload(rawFile);
      });
    },
    upload(rawFile) {
      this.$refs.uploadInput.value = null;
       if (typeof XMLHttpRequest !== "undefined") {
         //这里使用了两种方式,fetch和原生方式,由于fetch不支持获取上传的进度,如果不需要进度条或者自己模拟进度或者XMLHttpRequest对象不存在的时候,使用fetch请求上传逻辑会更简单一些
         this.xhrSubmit(rawFile);
       } else {
         this.fetchSubmit(rawFile);
       }
    },
    xhrSubmit(rawFile) {  //ajax请求上传图片
      const _this = this;
      let option = {
        file: rawFile,
        data: this.data,
        filename: this.name || "file",
        action: this.action,
        headers:this.headers,
        onProgress(e) {
          _this.$emit("progress",e)
        },
        onSuccess(res) {
           _this.$emit("success",res)
        },
        onError(err) {
          _this.$emit("error",err)
        }
      }
      let send = async option => {
        await sendRequest(option); //这里用了个异步方法,按次序执行this.sendRequest方法,参数为文件列表包装的每个对象,this.sendRequest下面紧接着介绍
      };
      send(option);
    },
    fetchSubmit(rawFile) { //fetch上传图片
        const _this = this;
      let keys = Object.keys(this.data),
        values = Object.values(this.data),
        action = this.action;
        let tempArr=[rawFile];
      const promises = tempArr.map(each => {
        each.status = "uploading";
        let data = new FormData();
        data.append(this.name || "file", each);
        keys.forEach((one, index) => data.append(one, values[index]));
        return fetch(action, {
          method: "POST",
          headers: {
            "Content-Type": "application/x-www-form-urlencoded"
          },
          body: data
        })
          .then(res => res.text())
          .then(res => JSON.parse(res)); //这里res.text()是根据返回值类型使用的,应该视情况而定
      });
      Promise.all(promises)
        .then(resArray => { //多线程同时开始,如果并发数有限制,可以使用同步的方式一个一个传,这里不再赘述。
          resArray.forEach((res, index) => {
            _this.$emit("finished",res)    
          });
        })    
    },
    submit() {
      this.$nextTick(() => {
        this.$refs.uploadInput.click();
      });
    }
  }
};
</script>
<style lang="less" scoped>
</style>

3. 引入组件myUpload.vue并使用:

<template>
	<div class="index">
		<my-upload 
			ref='upload'
			action="http://xxxxxxxxx:8080/upload"
			:data="{token:'ace'}"
			@progress='onProgress'
			@success='onSuccess'
			@error='onError'
			@finished='onFinished'
			>
		</my-upload>
		<button class="btn" @click="upload">点击上传</button>
	</div>
</template>

<script>
	import MyUpload from "@/components/myUpload.vue"
	export default {
		components:{
			MyUpload
		},
		methods:{
			upload(){ //点击上传
				this.$nextTick(()=>{
					this.$refs.upload.submit();
				})
			},
			onError(err){ //ajax上传失败
				console.log(err)
				console.log("err")
			},
			onSuccess(res){ //ajax上传成功
				console.log(res)
				console.log("success")
			},
			onProgress(e){ //ajax上传进度
				console.log(e)
				console.log("progress")
			},
			onFinished(e){  //fetch请求的上传结果
				console.log(e)
				console.log("finished")
			}
		}
			
	}
</script>

 

最后

以上就是苗条电话为你收集整理的Vue封装基于ajax和fetch两种方式上传文件组件完整代码的全部内容,希望文章能够帮你解决Vue封装基于ajax和fetch两种方式上传文件组件完整代码所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(39)

评论列表共有 0 条评论

立即
投稿
返回
顶部