当前位置:网站首页>Vant3+ts encapsulates uploader upload image component

Vant3+ts encapsulates uploader upload image component

2022-06-12 17:48:00 Enthusiastic learning

Because this component is used many times in the project So I sealed it myself

vant The components of need to be in

:after-read Then upload the image to the server

Select or take photos on your mobile phone The return format is [{name:xxx,data:base64,xxxxx},{name:xxx,data:base64,xxxxx}]

and Component echo is based on flie Object or URL

So before uploading hold Back to base64 Turn into file object

You need to compress the image before uploading it to the interface

  The code of the whole component is as follows

The logic of uploading pictures is First step , hold fileNames Upload to the interface provided in the background The return format is {url:xxx,path:xxx,contentType:xxx}, The second step , The return of url put Ask for file The request succeeds only when the object is transferred to the background , The third step , Taking the first step back path Send it to the background to return the picture URL( My echo here is based on url)

In the code count Pass values to the parent component only after all the interface requests are completed

<template>
  <van-uploader v-model="imgList" :max-count="limit" :multiple="multiple" :before-delete="beforeDeleteBack"
    :after-read="afterRead" :accept="fileType" :disabled="disabled" @click-upload="handleClick" />

</template>
<script lang="ts" setup>
import { reactive, ref, toRefs, watch, nextTick, unref } from 'vue'
import { Toast, Dialog } from 'vant'
import AjaxTestService from '@/api/test'
import { getPhoto } from '@/utils/nativeAPI'
import ImageCompressor from 'image-compressor.js'
import type {
  UploaderProps,
  UploaderInstance,
  UploaderResultType,
  UploaderFileListItem,
} from 'vant'
interface Props {
  imgList: Array<any> // File address - Two way binding 
  limit?: number // Number of documents 
  multiple?: boolean // Whether to choose more than one 
  fileType?: string // file type 
  disabled?: boolean // Whether to disable uploading 
}
const props = withDefaults(defineProps<Props>(), {
  limit: 4,
  multiple: true,
  fileType: 'image/*',
  disabled: false
})
const imgList = ref<Array<any>>([])
const emit = defineEmits<{
  (e: "update:imgList", imgList: any): void;
  (e: "fileList", filePath: any): void;
}>();
watch(
  () => props.imgList,
  val => {
    console.log(unref(val), "watch monitor imgList");
    // console.log(imgList.value.length, " The length of the picture ");

    imgList.value = val.map(v => {
      if (typeof v == 'string') {
        return { url: v }
      }
      else {
        return v
      }
    });
  },
  { immediate: true, deep: true }
);

// Delete pictures 
function beforeDeleteBack(file: any, detail: any) {
  console.log(" Delete operation :file", file, "detail,", detail)
  console.log(imgList.value, " From here img")
  // return new Promise<boolean>((resolve, reject) => {
  Dialog.confirm({
    confirmButtonText: ' confirm ',
    cancelButtonText: ' Cancel ',
    message: ' Confirm to delete the fault picture ',
  })
    .then((res) => {
      console.log(tempFile, " Delete ")
      tempFile.splice(detail.index, 1)
      imgList.value.splice(detail.index, 1)
      emit("update:imgList", imgList.value);
      Toast({
        message: ' Delete successful ',
        icon: 'checked',
        iconSize: '20px',
        className: 'tipToast'
      })

      // resolve(true)
    })

    .catch((error) => {
      // Toast({
      //   message: ' Cancelled ',
      // })
      // reject(error)
    })
  // })
}

// take base64 Convert to blob File stream 
function dataURLtoBlob(dataurl: any) {
  let arr = dataurl.split(',')
  let mime = arr[0].match(/:(.*?);/)[1]
  let bstr = window.atob(arr[1])
  let n = bstr.length
  let u8arr = new Uint8Array(n)
  console.log(mime, "mime")
  while (n--) {
    u8arr[n] = bstr.charCodeAt(n);
  }
  return new Blob([u8arr], { type: mime });
}
// then blob Convert to file
function blobToFile(theBlob: any, fileName: any) {
  theBlob.lastModifiedDate = new Date();
  theBlob.name = fileName;
  return theBlob;
}
// call 
// var blob = dataURLtoBlob(base64Data);
// var file = blobToFile(blob, imgName);


// take base64 turn file  object   Because again ios  There is an adaptation problem, so this method is not used .
function base64ToFile(urlData: any, fileName: string) {
  let arr = urlData.split(',');
  let mime = arr[0].match(/:(.*?);/)[1];
  let bytes = window.atob(arr[1]); //  decode base64
  let n = bytes.length
  let ia = new Uint8Array(n);
  while (n--) {
    ia[n] = bytes.charCodeAt(n);
  }
  //u8arr
  return new File([ia], fileName, { type: mime });
}

// Click the upload area to trigger the event   First, put fanhuide blobToFile(v.data, v.name)
function handleClick() {
  console.log(" Click upload event to trigger ")
  getPhoto((res: any) => {
    console.log(typeof res, " Select the file type to return ")
    // console.log(res, " Select the returned file ")
    if (typeof res == 'string') {
      res = JSON.parse(res)
      res = res.map((v: any) => {
        return {
          type: 'image/jpeg',
          name: v.name,
          file: blobToFile(dataURLtoBlob(v.data), v.name)
        }
      })
    }
    afterRead(res)
  })
}
// You need to compress the image before uploading 
function compressFile(file: any, callback: (cres: any) => void) {
  new ImageCompressor(file, {
    quality: 0.4, // The compression quality 
    width: 500,
    height: 500,
    checkOrientation: false, // Flip the picture , The default is false
    success(result) {
      console.log(result, "result Compressed files ")
      callback(result);
    },
    error(e) {
      JSON.stringify(e)
    }
  })
}
//
function beforeRead() {
  console.log(" Click upload event to trigger ")
}

// Upload files to the server 
let tempFile: { file: { name: any; }; path: string; url: string; name: any, type: string }[] = []
function afterRead(file: any) {
  console.log(file, " stay afterRead")
  if (file.length) { // instanceof Array  The radio 
    tempFile = tempFile.concat(file)
  } else {       // multi-select 
    tempFile.push(file) 
  }
  if (tempFile.length > 4) {
    console.log(tempFile.length, " In judgment tempFile The length of ")
    tempFile.splice(4)
  }
  console.log(typeof tempFile, "typeof tempFile")
  console.log(tempFile, "tempFile Processing is complete ")
  console.log(tempFile.length, "tempFile The length of processing completed ")
  // There is no problem with this cycle on the browser side , The format on the mobile phone returns [{name:xxx,data:base64},{name:xxx}]
  let parma = {
    fileNames: tempFile.map((fileItem: { file: { name: any; }; }) => fileItem.file.name).join(",")
  }
  // console.log(parma, ' Print parameters ')
  // The interface provided by the background obtains the temporary path    
  AjaxTestService.getUploadUrl(parma).then((res) => {
    let count = 0
    res.data.forEach((item: { url: any; path: any, contentType: string }, index: any) => {
      tempFile[index].path = item.path
      tempFile[index].type = item.contentType
      // This step is compression     
      compressFile(tempFile[index].file, (cres: any) => {
        console.log(cres, ' Compressed file file')
        // Take the returned url put  The request is considered to be successful in uploading the picture   
        AjaxTestService.uploadImg(item.url, cres, item.contentType).then(_res => {
          console.log(_res, " Upload successful ")
          // Return temporary picture information according to the background interface 
          AjaxTestService.getTempFileUrl({ pathNames: item.path }).then(resUrl => {
            console.log(res, " Get temporary url")
            tempFile[index].url = resUrl.data[0]
            count += 1
            if (count == res.data.length) {
              imgList.value = tempFile
              emit("update:imgList", tempFile)
              console.log(tempFile.length, "tempFile The length of ")
              console.log(tempFile, "3 Step interface completed  imgList")

            }

          })

        }).catch(err => {

        })
      })

    });

  }).catch(err => {

  })


}
defineExpose({
  // handleForm
});
</script>
<style scoped lang="scss">
</style>

原网站

版权声明
本文为[Enthusiastic learning]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/163/202206121740566111.html