原生js上传文件的几种方式

页面结构

html部分

<input
      type="file"
      name="file"
      id="input1"
 />
 <button id="btn">取消上传</button>
<img src="" alt="" id="img" style="display: none" />

模拟上传

const myFile = document.querySelector('#input1') 
const btn = document.querySelector('#btn')
const myImg = document.querySelector('#img')
// 定义一个变量,接受上传函数
let cancelUpload = null
     function changeHandle() {
        // 判断文件是否存在
        if (!myFile.files.length) {
          return
        }
        // 获取文件信息
        const file = myFile.files[0]
        // 验证
        if (!validateFile(file)) return
        // 创建文件读取器
        const reader = new FileReader()
        // 文件读取成功后操作
        reader.onload = e => {
          myImg.src = reader.result // 将读取后的结果赋值给<img>
        }
        // 读取文件,将文件内容读取成一个 data:URL(base64编码) 格式的字符串
        reader.readAsDataURL(file)

        // 上传文件过程
        cancelUpload = upload(
          file,
          function (val) {
            // 上传文件过程执行的函数
            setProgress(val)
          },
          function (resp) {
            // 完成上传执行的函数
            console.log(resp)
            myImg.style.display = 'block'
          }
        )
      }
      // 文件格式验证
      function validateFile(file) {
        const sizeLimit = 1 * 1024 * 1024
        const fileType = ['.jpg', '.png', 'jpeg', '.webp', 'gif']
        if (file.size > sizeLimit) {
          alert('文件尺寸过大')
          return
        }
        const name = file.name.toLowerCase()
        if (!fileType.some(e => name.endsWith(e))) {
          alert('文件格式不对')
          return
        }
        return true
      }
      // 函数操作
      function setProgress(val) {
        console.log(val)
      }
      // 模拟数据进行上传
      function upload(file, onProgress, onFinish) {
        let p = 0
        onProgress(p)
        const timer = setInterval(() => {
          p += 2
          onProgress(p)
          if (p >= 100) {
            onFinish('上传结束,服务器返回的结果')
            clearInterval(timer)
          }
        }, 50)
        // 返回一个中止函数
        return function () {
          clearInterval(timer)
        }
      }
      // 取消上传
      function cancel() {
        cancelUpload && cancelUpload()
        myFile.value = null
      }
      // 取消文件上传
      btn.addEventListener('click', cancel)
      

XMLHttpRequest上传文件(以下的上传文件方法看服务器端给出的要求来)

    /* 
        XHR上传
        POST /upload/single HTTP
        host: test.com:9527
        Content-Type:multipart/form-data;
      */
    // 将上面的upload函数替换掉
   function upload(file, onProgress, onFinish){
        onProgress(0)
         // 初始化一个 XMLHttpRequest 实例对象
        const xhr = new XMLHttpRequest()
        // 创建了一个 FormData 实例
        const form = new FormData()
        // 追加文件数据
        form.append('avatar',file)
        // 初始化一个请求
        xhr.open('POST','http://test.com:9527/upload/single')
        // 请求完成
        xhr.onload = function(){
          // 接受服务端传来的数据
          const resp = JSON.parse(xhr.responseText)
          onFinish(resp)
        }
        // 请求失败
        xhr.onerror = function(e){
          alert('请求失败',e)
        }
        //设置超时时间 (可选)
        xhr.timeout = 10000;  
        xhr.ontimeout = function(event){  
       alert('请求超时!');  
      }
         // 上传进度
        xhr.upload.onprogress = e => {
          const percent = Math.floor((e.loaded / e.total) * 100)
          onProgress(percent)
        }
        // 发送请求
        xhr.send(form)
        // 返回一个取消上传的函数
        return function() {
          xhr.abort()
        }
      }

base64上传文件

/* 
        base64上传
        POST /upload/single HTTP
        host: test.com:9527
        Content-Type:application/json
        body: '{
          'ext':'.jpg',
          'avatar':'base64格式数据'
        }'
      */
      // 将上面的upload函数替换掉
      function uploadBase64(file, onProgress, onFinish) {
        const reader = new FileReader()
        reader.onload = function (e) {
          onProgress(0)
          const xhr = new XMLHttpRequest()
          const ext = '.' + file.type.split('/').at(-1)
          const base64 = e.target.result.split('.').pop()
          xhr.open('POST', 'http://test.com:9527/upload/single')
          xhr.setRequestHeader('Content-Type', 'application/json')
          // 请求完成
          xhr.onload = function () {
            const resp = JSON.parse(xhr.responseText)
            onFinish(resp)
          }
          // 请求失败
          xhr.onerror = function (e) {
            alert('请求失败', e)
          }
          //设置超时时间 (可选)
          xhr.timeout = 10000;  
          xhr.ontimeout = function(event){  
         alert('请求超时!');  
        }
          // 上传进度
          xhr.upload.onprogress = e => {
          const percent = Math.floor((e.loaded / e.total) * 100)
            onProgress(percent)
          }
          xhr.send(
            JSON.stringify({
              ext,
              avatar: base64,
            })
          )
        }
        // 读取文件,将文件内容读取成一个 data:URL(base64编码) 格式的字符串
        reader.readAsDataURL(file)
        // 返回一个取消上传的函数
        return function () {
          xhr && xhr.abort()
        }
      }

拖拽上传

新增html部分
<style>
      .drag::before {
        content: '+';
        position: absolute;
        width: 100%;
        height: 100%;
        top: 50%;
        left: 50%;
        font-size: 80px;
        transform: translate(-50%, -50%);
        color: rgba(0, 0, 0, 0.2);
        /* transform: scale(5); */
      }
      .drag input {
        position: absolute;
        left: 0;
        width: 100%;
        height: 100%;
        /* opacity: 0; */
      }
</style>

<div
      class="drag"
      style="
        position: relative;
        width: 200px;
        height: 200px;
        border: 1px solid #270ab6;
        text-align: center;
        line-height: 200px;
        cursor: pointer;
      "
    >
      <!-- <input type="file" name="" id="dragFile" /> 
      此为第二种拖拽上传方式,选用此种方式,加上上面的style
      -->
      拖动文件到此上传
</div>
js部分
const dragDiv = document.querySelector('.drag')
const dragFile = document.querySelector('#dragFile')

      // 拖动上传
      // 监听可拖动的元素或者被选择的文本进入该元素时触发
      dragDiv.addEventListener('dragenter', e => {
        // 取消默认事件
        e.preventDefault()
      })
      // 监听可拖动的元素或者被选择的文本被拖进该元素时(每几百毫秒)触发
      dragDiv.addEventListener('dragover', e => {
        e.preventDefault()
      })
      // 上面两步使该元素成为可拖拽元素
      // 监听元素或选中的文本被放置在该元素上时触发
      dragDiv.addEventListener('drop', e => {
        e.preventDefault()
        // 接受拖放操作时,传输的数据
        const form = e.dataTransfer.files
        console.log(e.dataTransfer); // FileList
        // 判断被拖拽进来元素是否是文件
        if (!e.dataTransfer.types.includes('Files')) {
          alert('仅支持拖拽文件')
          return
        }
        // 限制文件上传一个
        if (form.length > 1) {
          alert('仅支持上传一个文件')
          return
        }
        // 将数据赋值给第一个input元素
        myFile.files = form
        // 手动触发changeHandle函数
        changeHandle()
     })
     // 第二种方法,在drag元素里面添加一个input元素,将其大小覆盖drag元素
     // 监听第二个input元素内容的改变即可
      dragFile.addEventListener('change', e => {
        // 将数据赋值给第一个input元素
        myFile.files = e.target.files
        // 手动触发changeHandle函数
        changeHandle()
      })
  • 11
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值