Skip to content

Commit

Permalink
feat: useUpload
Browse files Browse the repository at this point in the history
  • Loading branch information
nemo-shen committed Feb 14, 2024
1 parent 39279c6 commit 0856f32
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 11 deletions.
60 changes: 51 additions & 9 deletions packages/core/useUpload/index.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,31 @@
import { ref } from 'vue'

/**
* TODO:
* - [ ] 允许并发上传数量,默认1
* - [ ] 允许设置失败重传次数,默认0
* - [ ] 限制可上传的文件大小,默认Infinity表示不限制
*/

interface UseUploadOptions {
url: string
multiple?: boolean
accept?: string
}

interface UseUploadFile {
file: File
name: string
ext: string
url: string
status: 'ready' | 'uploading' | 'success' | 'error'
error?: Error
}

interface UseUploadReturn {
upload: () => void
append: (file: File | File[]) => void
files: Ref<UseUploadFile[]>
}

interface UploadOptions {
Expand All @@ -29,15 +46,36 @@ const uploadFile = (options: UploadOptions, file: File) => {
})
}

type Base64 = string

const useFileReader = (file: File): Promise<Base64> => new Promise((resolve) => {
const reader = new FileReader()
reader.onload = (e) => {
resolve(e.target.result)
}
reader.readAsDataURL(file)
})

const genUploadFile = async (file: File): UseUploadFile => ({
file,
name: file.name.split('.')[0],
ext: file.name.split('.')[1],
data: await useFileReader(file),
url: '',
status: 'ready',
})

export const useUpload = (options: UseUploadOptions): UseUploadReturn => {
const { url, multiple = false, accept = '' } = options
const acceptList = accept.split(',').map((type) => type.trim())
const files = ref<File[]>([])
const files = ref<UseUploadFile[]>([])

const upload = () => {
const result = files.value.map((file) => uploadFile({ url }, file))
Promise.all(result).then((res) => {
console.log(res)
files.value.forEach((file, index) => {
uploadFile({ url }, file)
.then((_result) => {
files.value[index].status = 'success'
})
})
}

Expand All @@ -54,27 +92,31 @@ export const useUpload = (options: UseUploadOptions): UseUploadReturn => {
})
}

const append = (file: File | File[]) => {
const append = async (file: File | File[]) => {
if (!multiple && Array.isArray(file)) {
console.warn(
'if you want upload multiple files, set options multiple is `true`'
)
}
if (multiple) {
if (!(file as File[]).every(validFileType)) {
throw new Error("Have some File reject");
throw new Error('Have some File reject')
}
files.value = [...files.value, ...(file as File[])]
files.value = [
...files.value,
...await (file as File[]).map(async (f) => genUploadFile(f)),
]
} else {
if (!validFileType(file as File)) {
throw new Error("File type reject.");
throw new Error('File type reject.')
}
files.value.push(file as File)
files.value.push(await genUploadFile(file))
}
}

return {
upload,
append,
files,
}
}
15 changes: 13 additions & 2 deletions src/demo/UseUpload.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,26 @@
import { watch, ref, h, VNode } from 'vue'
import { useUpload } from '@noi/core'
const { upload, append } = useUpload({ url: '#', accept: 'image/*' })
const url = 'https://run.mocky.io/v3/da20c84f-fbe5-4510-8f24-80fa61474790'
const { upload, append, files } = useUpload({ url })
const inputChange = (event) => {
append(event.target.files[0])
}
</script>

<template>
<div v-for="(item, index) in files" :key="index">
<!-- <img :src="item.data" alt="" /> -->
{{ item.name }}
<br>
{{ item.ext }}
<br />
{{ item.status }}
<hr />
</div>
<br />
<input accept="" type="file" @change="inputChange" />
<br>
<br />
<button @click="upload">upload</button>
</template>

0 comments on commit 0856f32

Please sign in to comment.