업로드

업로드 (Upload)

출처: 문서

본문

클릭 또는 드래그 앤 드롭으로 파일을 업로드하는 컴포넌트예요.

기본 사용법 ​

slot을 사용해 업로드 버튼의 타입과 텍스트를 커스터마이즈할 수 있어요. limit와 on-exceed를 설정하면 허용되는 최대 업로드 개수를 제한하고, 한도를 초과했을 때의 동작을 지정할 수 있어요. 그리고 before-remove 훅에서 파일 삭제를 중단할 수도 있죠.

  • jpg/png 파일, 크기 500KB 미만
  • element-plus-logo.svg (press delete to remove)
  • element-plus-logo2.svg (press delete to remove)
<template>
  <el-upload
    v-model:file-list="fileList"
    action="https://run.mocky.io/v3/9d059bf9-4660-45f9-925d-a31b31d8f1c5"
    :limit="3"
    :on-exceed="handleExceed"
    :before-remove="beforeRemove"
    @remove="handleRemove"
    @preview="handlePreview"
  >
    <el-button type="primary">Click to upload</el-button>
    <template #tip>
      <div class="el-upload__tip">
        jpg/png files with a size less than 500KB.
      </div>
    </template>
  </el-upload>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'

import type { UploadProps, UploadUserFile } from 'element-plus'

const fileList = ref<UploadUserFile[]>([
  {
    name: 'element-plus-logo.svg',
    url: 'https://element-plus.org/images/element-plus-logo.svg',
  },
  {
    name: 'element-plus-logo2.svg',
    url: 'https://element-plus.org/images/element-plus-logo.svg',
  },
])

const handleRemove: UploadProps['onRemove'] = (file, uploadFiles) => {
  console.log(file, uploadFiles)
}

const handlePreview: UploadProps['onPreview'] = (uploadFile) => {
  console.log(uploadFile)
}

const handleExceed: UploadProps['onExceed'] = (files, uploadFiles) => {
  ElMessage.warning(
    `The limit is 3, you selected ${files.length} files this time, add up to ${
      files.length + uploadFiles.length
    } totally`
  )
}

const beforeRemove: UploadProps['beforeRemove'] = (uploadFile, uploadFiles) => {
  return ElMessageBox.confirm(
    `Cancel the transfer of ${uploadFile.name} ?`
  ).then(
    () => true,
    () => false
  )
}
</script>

이전 파일 덮어쓰기 (Cover Previous File) ​

limit와 on-exceed를 설정하면 새 파일을 선택할 때 이전 파일을 자동으로 대체해요.

  • upload to server, limit 1 file, new file will cover the old file
<template>
  <el-upload
    ref="upload"
    v-model:file-list="fileList"
    action="#"
    :limit="1"
    :on-exceed="handleExceed"
  >
    <el-button type="primary">Click to upload</el-button>
    <template #tip>
      <div class="el-upload__tip">
        upload to server, limit 1 file, new file will cover the old file
      </div>
    </template>
  </el-upload>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { genFileId } from 'element-plus'

import type { UploadInstance, UploadProps, UploadRawFile } from 'element-plus'

const upload = ref<UploadInstance>()

const handleExceed: UploadProps['onExceed'] = (files) => {
  upload.value!.clearFiles()
  const file = files[0] as UploadRawFile
  file.uid = genFileId()
  upload.value!.handleStart(file)
}

const submitUpload = () => {
  upload.value!.submit()
}
</script>

사용자 아바타 (User Avatar) ​

before-upload 훅을 사용해 업로드 파일의 형식과 크기를 제한할 수 있어요.

<template>
  <el-upload
    class="avatar-uploader"
    action="https://run.mocky.io/v3/9d059bf9-4660-45f9-925d-a31b31d8f1c5"
    :show-file-list="false"
    :on-success="handleAvatarSuccess"
    :before-upload="beforeAvatarUpload"
  >
    <img v-if="imageUrl" :src="imageUrl" class="avatar" />
    <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
  </el-upload>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { ElMessage } from 'element-plus'
import { Plus } from '@element-plus/icons-vue'
import type { UploadProps } from 'element-plus'

const imageUrl = ref('')

const handleAvatarSuccess: UploadProps['onSuccess'] = (
  response,
  uploadFile
) => {
  imageUrl.value = URL.createObjectURL(uploadFile.raw!)
}

const beforeAvatarUpload: UploadProps['beforeUpload'] = (rawFile) => {
  if (rawFile.type !== 'image/jpeg') {
    ElMessage.error('Avatar picture must be JPG format!')
    return false
  } else if (rawFile.size / 1024 / 1024 > 2) {
    ElMessage.error('Avatar picture size can not exceed 2MB!')
    return false
  }
  return true
}
</script>

포토 월 (Photo Wall) ​

list-type을 사용해 fileList 스타일을 바꿀 수 있어요.

<template>
  <el-upload
    v-model:file-list="fileList"
    action="https://run.mocky.io/v3/9d059bf9-4660-45f9-925d-a31b31d8f1c5"
    list-type="picture-card"
    :on-preview="handlePictureCardPreview"
    :on-remove="handleRemove"
  >
    <el-icon><Plus /></el-icon>
  </el-upload>

  <el-dialog v-model="dialogVisible">
    <img w-full :src="dialogImageUrl" alt="Preview Image" />
  </el-dialog>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { Delete, Download, Plus, ZoomIn } from '@element-plus/icons-vue'

import type { UploadFile } from 'element-plus'

const dialogImageUrl = ref('')
const dialogVisible = ref(false)
const disabled = ref(false)

const handleRemove = (file: UploadFile) => {
  console.log(file)
}

const handlePictureCardPreview = (file: UploadFile) => {
  dialogImageUrl.value = file.url!
  dialogVisible.value = true
}

const handleDownload = (file: UploadFile) => {
  console.log(file)
}
</script>

썸네일이 있는 파일 목록 (File List with Thumbnail) ​

  • jpg/png 파일, 크기 500kb 미만
  • food.jpeg (press delete to remove)
  • food2.jpeg (press delete to remove)
<template>
  <el-upload
    v-model:file-list="fileList"
    class="upload-demo"
    action="https://run.mocky.io/v3/9d059bf9-4660-45f9-925d-a31b31d8f1c5"
    :on-preview="handlePreview"
    :on-remove="handleRemove"
    :before-remove="beforeRemove"
    multiple
    :limit="3"
    :on-exceed="handleExceed"
  >
    <el-button type="primary">Click to upload</el-button>
    <template #tip>
      <div class="el-upload__tip">
        jpg/png files with a size less than 500kb
      </div>
    </template>
  </el-upload>
</template>

<script setup lang="ts">
import { ref } from 'vue'

import type { UploadProps, UploadUserFile } from 'element-plus'

const fileList = ref<UploadUserFile[]>([
  {
    name: 'food.jpeg',
    url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100',
  },
  {
    name: 'food2.jpeg',
    url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100',
  },
])

const handleRemove: UploadProps['onRemove'] = (uploadFile, uploadFiles) => {
  console.log(uploadFile, uploadFiles)
}

const handlePreview: UploadProps['onPreview'] = (file) => {
  console.log(file)
}
</script>

파일 목록 제어 (File List Control) ​

on-change 훅 함수를 사용해 업로드 파일 목록을 제어할 수 있어요.

  • jpg/png 파일, 크기 500kb 미만
  • food.jpeg (press delete to remove)
  • food2.jpeg (press delete to remove)
<template>
  <el-upload
    v-model:file-list="fileList"
    class="upload-demo"
    action="https://run.mocky.io/v3/9d059bf9-4660-45f9-925d-a31b31d8f1c5"
    :on-change="handleChange"
  >
    <el-button type="primary">Click to upload</el-button>
  </el-upload>
</template>

<script setup lang="ts">
import { ref } from 'vue'

import type { UploadProps, UploadUserFile } from 'element-plus'

const fileList = ref<UploadUserFile[]>([
  {
    name: 'food.jpeg',
    url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100',
  },
  {
    name: 'food2.jpeg',
    url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100',
  },
])

const handleChange: UploadProps['onChange'] = (uploadFile, uploadFiles) => {
  fileList.value = fileList.value.slice(-3)
}
</script>

드래그 업로드 (Drag to Upload) ​

파일을 특정 영역으로 드래그해서 업로드할 수 있어요.

  • jpg/png 파일, 크기 500kb 미만
<template>
  <el-upload
    class="upload-demo"
    drag
    action="https://run.mocky.io/v3/9d059bf9-4660-45f9-925d-a31b31d8f1c5"
    multiple
  >
    <el-icon class="el-icon--upload"><upload-filled /></el-icon>
    <div class="el-upload__text">
      Drop file here or <em>click to upload</em>
    </div>
    <template #tip>
      <div class="el-upload__tip">
        jpg/png files with a size less than 500kb
      </div>
    </template>
  </el-upload>
</template>

<script setup lang="ts">
import { UploadFilled } from '@element-plus/icons-vue'
</script>

디렉토리 업로드 (Upload Directory) 2.13.1 ​

directory prop으로 폴더 업로드를 활성화할 수 있어요. 활성화하면 폴더만 선택할 수 있고, 폴더를 선택하면 폴더 안의 파일들이 평탄화(flatten)되어 사용돼요.

<template>
  <el-upload
    action="#"
    directory
    :auto-upload="false"
    :on-change="handleChange"
  >
    <el-button type="primary">Select folder</el-button>
  </el-upload>
</template>

<script setup lang="ts">
import { UploadFilled } from '@element-plus/icons-vue'

import type { UploadFile, UploadFiles } from 'element-plus'

const handleChange = (uploadFile: UploadFile, uploadFiles: UploadFiles) => {
  console.log(uploadFile, uploadFiles)
}
</script>

수동 업로드 (Manual Upload) ​

  • upload to server, jpg/png 파일, 크기 500kb 미만
<template>
  <el-upload
    ref="uploadRef"
    v-model:file-list="fileList"
    action="https://run.mocky.io/v3/9d059bf9-4660-45f9-925d-a31b31d8f1c5"
    :auto-upload="false"
  >
    <template #trigger>
      <el-button type="primary">select file</el-button>
    </template>
    <el-button class="ml-3" type="success" @click="submitUpload">
      upload to server
    </el-button>
    <template #tip>
      <div class="el-upload__tip">
        jpg/png files with a size less than 500kb
      </div>
    </template>
  </el-upload>
</template>

<script setup lang="ts">
import { ref } from 'vue'

import type { UploadInstance } from 'element-plus'

const uploadRef = ref<UploadInstance>()

const submitUpload = () => {
  uploadRef.value!.submit()
}
</script>

API ​

Attributes ​

Name Description Type Default
action (required) request URL. string #
headers request headers. object —
method set upload request method. string post
multiple whether uploading multiple files is permitted. boolean false
data additions options of request. support Awaitable data and Function since v2.3.13. object / Function {}
name key name for uploaded file. string file
with-credentials whether cookies are sent. boolean false
show-file-list whether to show the uploaded file list. boolean true
drag whether to activate drag and drop mode. boolean false
accept accepted file types, will not work when thumbnail-mode === true. string ''
crossorigin native attribute crossorigin. enum —
on-preview hook function when clicking the uploaded files. Function —
on-remove hook function when files are removed. Function —
on-success hook function when uploaded successfully. Function —
on-error hook function when some errors occurs. Function —
on-progress hook function when some progress occurs. Function —
on-change hook function when select file or upload file success or upload file fail. Function —
on-exceed hook function when limit is exceeded. Function —
before-upload hook function before uploading with the file to be uploaded as its parameter. If false is returned or a Promise is returned and then is rejected, uploading will be aborted. Function —
before-remove hook function before removing a file with the file and file list as its parameters. If false is returned or a Promise is returned and then is rejected, removing will be aborted. Function —
file-list / v-model:file-list default uploaded files. array []
list-type type of file list. enum text
auto-upload whether to auto upload file. boolean true
http-request override default xhr behavior, allowing you to implement your own upload-file's request. Function ajaxUpload (see)
disabled whether to disable upload. boolean false
limit maximum number of uploads allowed. number —
directory (2.13.1) whether to support uploading directory. After enabling it, only folders can be selected, and after selecting a folder, the files within the folder will be flattened. boolean false

Slots ​

Name Description Type
default customize default content. -
trigger content which triggers file dialog. -
tip content of tips. -
file content of thumbnail template. object

Exposes ​

Name Description Type
abort cancel upload request. When a file is specified, abort the corresponding pending upload; when no file is specified, abort all pending uploads. Function
submit upload the file list manually. Function
clearFiles clear the file list (this method is not supported in the before-upload hook). Function
handleStart select the file manually. Function
handleRemove remove the file manually. file and rawFile has been merged. rawFile will be removed in v2.2.0. Function

타입 선언 (Type Declarations) ​

type UploadFiles = UploadFile[]

type UploadUserFile = Omit<UploadFile, 'status' | 'uid'> &
  Partial<Pick<UploadFile, 'status' | 'uid'>>

type UploadStatus = 'ready' | 'uploading' | 'success' | 'fail'

type Awaitable<T> = Promise<T> | T

type Mutable<T> = { -readonly [P in keyof T]: T[P] }

interface UploadFile {
  name: string
  percentage?: number
  status: UploadStatus
  size?: number
  response?: unknown
  uid: number
  url?: string
  raw?: UploadRawFile
}

interface UploadProgressEvent extends ProgressEvent {
  percent: number
}

interface UploadRawFile extends File {
  uid: number
  isDirectory?: boolean
}

interface UploadRequestOptions {
  action: string
  method: string
  data: Record<string, string | Blob>
  filename: string
  file: UploadRawFile
  headers: Headers | Record<string, string>
  onError: (evt: UploadAjaxError) => void
  onProgress: (evt: UploadProgressEvent) => void
  onSuccess: (response: any) => void
  withCredentials: boolean
}

더 알아보기 (Learn more)