Upload 업로드
파일을 업로드할 때 사용하는 컴포넌트예요.
출처: 문서
본문
언제 사용하나요
파일을 백엔드 서버로 올려야 할 때 사용해요.
기본 사용법
:::demo
<template>
<d-upload v-model="uploadedFiles" :upload-options="uploadOptions" />
</template>
<script>
import { ref } from 'vue';
export default {
setup() {
const uploadedFiles = ref([]);
const uploadOptions = ref({
uri: 'https://run.mocky.io/v3/132b3ea3-23ea-436b-aed4-c43ef9d116f0',
});
return {
uploadedFiles,
uploadOptions,
};
},
};
</script>
:::
여러 파일 업로드
multiple 속성을 쓰면 여러 파일 업로드를 지원하고, limit 속성으로 파일 수 상한을 정할 수 있어요. 업로드 수가 제한을 넘으면 on-exceed 훅 함수가 호출돼요.
:::demo
<template>
<d-upload
v-model="uploadedFiles"
:upload-options="uploadOptions"
multiple
:limit="2"
:on-exceed="handleExceed"
:on-change="handleChange"
:on-preview="onPreview"
/>
</template>
<script>
import { ref } from 'vue';
export default {
setup() {
const uploadedFiles = ref([]);
const uploadOptions = ref({
uri: 'https://run.mocky.io/v3/132b3ea3-23ea-436b-aed4-c43ef9d116f0',
});
const handleExceed = (files, uploadFiles) => {
console.log('onExceed:', files);
console.log('onExceed:', uploadFiles);
throw new Error('文件数上限为 2');
};
const handleChange = (files, uploadFiles) => {
console.log('onChange:', files);
console.log('onChange:', uploadFiles);
};
const onPreview = (file) => {
console.log('previewFile: ', file);
};
return {
uploadedFiles,
uploadOptions,
handleExceed,
handleChange,
onPreview,
};
},
};
</script>
:::
파일 드래그 업로드
:::demo
<template>
<d-upload v-model="uploadedFiles" :upload-options="uploadOptions" droppable />
</template>
<script>
import { ref } from 'vue';
export default {
setup() {
const uploadedFiles = ref([]);
const uploadOptions = ref({
uri: 'https://run.mocky.io/v3/132b3ea3-23ea-436b-aed4-c43ef9d116f0',
});
return {
uploadedFiles,
uploadOptions,
};
},
};
</script>
:::
수동 업로드와 비우기
auto-upload를 false로 설정하면 파일을 고른 직후 바로 업로드되는 동작을 막을 수 있어요. 이후 submit 메서드로 수동 업로드를 진행해요.
clearFiles 메서드를 사용하면 업로드된 파일과 선택된 파일을 모두 깔끔하게 비울 수 있어요.
:::demo
<template>
<div>
<d-upload ref="demoUpload" multiple v-model="uploadedFiles" :upload-options="uploadOptions" :auto-upload="false" />
<d-button @click="submit" style="margin-top: 20px">手动上传</d-button>
<d-button @click="clear" style="margin: 20px 0px 0px 10px;">清空文件</d-button>
</div>
</template>
<script>
import { defineComponent, ref } from 'vue';
export default defineComponent({
setup() {
const uploadedFiles = ref([]);
const uploadOptions = ref({
uri: 'https://run.mocky.io/v3/132b3ea3-23ea-436b-aed4-c43ef9d116f0',
});
const demoUpload = ref(null);
const submit = () => {
demoUpload.value.submit();
};
const clear = () => {
demoUpload.value.clearFiles();
};
return {
uploadedFiles,
uploadOptions,
demoUpload,
submit,
clear,
};
},
});
</script>
:::
업로드 막기
:::demo
<template>
<d-upload v-model="uploadedFiles" :upload-options="uploadOptions" disabled />
</template>
<script>
import { ref } from 'vue';
export default {
setup() {
const uploadedFiles = ref([]);
const uploadOptions = ref({
uri: 'https://run.mocky.io/v3/132b3ea3-23ea-436b-aed4-c43ef9d116f0',
});
return {
uploadedFiles,
uploadOptions,
};
},
};
</script>
:::
원하는 영역에서 업로드하기
:::demo 기본 slot을 사용하면 파일을 원하는 영역에서 업로드할 수 있어요.
<template>
<d-upload
class="upload-demo"
accept=".png"
v-model="uploadedFiles"
:upload-options="uploadOptions"
droppable
:on-success="onSuccess"
:on-error="onError"
:on-progress="onProgress"
:before-upload="beforeUpload"
@file-over="fileOver"
@file-drop="fileDrop"
@file-select="fileSelect"
@delete-uploaded-file="deleteUploadedFile"
>
<div class="upload-trigger">
<div><d-icon name="upload" size="24px"></d-icon></div>
<div style="margin-top: 20px;">
将文件拖到此处,或
<span class="link">点击上传</span>
</div>
</div>
<template v-slot:uploaded-files="slotProps">
<table class="table uploaded-files" v-if="slotProps.uploadedFiles.length > 0">
<tbody>
<tr v-for="(uploadedFile, index) in slotProps.uploadedFiles" :key="index" class="row">
<td width="50%">
<span>{{ uploadedFile.name }}</span>
</td>
<td width="25%">
<span>Uploaded</span>
</td>
<td>
<d-button size="xs" @click="(event) => slotProps.deleteFile(uploadedFile)">Delete</d-button>
</td>
</tr>
</tbody>
</table>
</template>
</d-upload>
</template>
<script>
import { ref, watch } from 'vue';
export default {
setup() {
const uploadedFiles = ref([
{
name: 'food.jpeg',
url: 'https://devui.design/home',
},
{
name: 'food2.jpeg',
url: 'https://devui.design/home',
},
]);
const uploadOptions = ref({
uri: 'https://run.mocky.io/v3/132b3ea3-23ea-436b-aed4-c43ef9d116f0',
});
const beforeUpload = (file) => {
console.log(file);
return true;
};
const onSuccess = (result) => {
console.log('success', result);
};
const onError = () => {
console.log(error);
};
const onProgress = (selectFile, uploadedFiles) => {
console.log('selectFile: ', selectFile);
console.log('uploadedFiles: ', uploadedFiles);
};
const fileOver = (fileInfo) => {
console.log('fileInfo:', fileInfo);
};
const fileDrop = (fileInfo) => {
console.log('fileInfo:', fileInfo);
};
const fileSelect = (fileInfo) => {
console.log('fileInfo:', fileInfo);
};
const deleteUploadedFile = (fileInfo) => {
console.log('fileInfo:', fileInfo);
};
watch(uploadedFiles, (newValue, oldValue) => {
console.log('uploadedFiles', {
newValue,
oldValue,
});
});
return {
uploadedFiles,
uploadOptions,
beforeUpload,
onSuccess,
onError,
onProgress,
fileOver,
fileDrop,
fileSelect,
deleteUploadedFile,
};
},
};
</script>
<style>
.upload-demo .upload-trigger {
background-color: #fff;
border: 1px dashed #d9d9d9;
border-radius: 6px;
box-sizing: border-box;
width: 360px;
height: 180px;
text-align: center;
cursor: pointer;
position: relative;
overflow: hidden;
display: flex;
flex-direction: column;
justify-content: center;
}
.upload-demo .upload-trigger .link {
color: #5e7ce0;
}
</style>
:::
이미지 업로드 예제
:::demo
<template>
<div class="img-container" v-if="!showUpload">
<img class="img-preview" />
<div class="delete-img" @click="handleDel">
<d-icon name="delete" size="14px"></d-icon>
</div>
</div>
<d-upload class="upload-demo-new" accept=".png" :upload-options="uploadOptions" :before-upload="beforeUpload" v-if="showUpload">
<div class="upload-trigger">
<d-icon name="add" size="24px"></d-icon>
</div>
</d-upload>
</template>
<script>
import { ref, watch, nextTick } from 'vue';
export default {
setup() {
const showUpload = ref(true);
const uploadOptions = ref({
uri: 'https://run.mocky.io/v3/132b3ea3-23ea-436b-aed4-c43ef9d116f0',
});
const beforeUpload = (file) => {
const reader = new FileReader();
reader.onload = async () => {
showUpload.value = false;
await nextTick();
document.getElementsByClassName('img-preview')[0].src = reader.result;
};
reader.readAsDataURL(file[0].file);
return false;
};
const handleDel = () => {
showUpload.value = true;
};
return {
uploadOptions,
beforeUpload,
showUpload,
handleDel,
};
},
};
</script>
<style>
.upload-demo-new .upload-trigger {
background-color: #fff;
border: 1px dashed #d9d9d9;
border-radius: 6px;
box-sizing: border-box;
width: 180px;
height: 180px;
text-align: center;
cursor: pointer;
position: relative;
overflow: hidden;
display: flex;
flex-direction: column;
justify-content: center;
}
.upload-demo .upload-trigger .link {
color: #5e7ce0;
}
.img-container {
position: relative;
}
.img-preview {
width: 180px;
height: 180px;
border-radius: 6px;
}
.delete-img {
width: 24px;
height: 24px;
background-color: #f7f7f9;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
position: absolute;
top: -12px;
left: 168px;
}
</style>
:::
Upload 파라미터
| 파라미터 | 타입 | 기본값 | 설명 | Demo 링크 |
|---|---|---|---|---|
| accept | string |
- | 선택, 파일 업로드로 제출 가능한 파일 타입 지정, 예: accept: '.xls,.xlsx,.png' |
임의 영역 업로드 |
| before-upload | boolean Promise<boolean> |
- | 선택, 업로드 전 콜백. true or false 반환으로 파일 업로드 여부 제어. 파라미터는 파일 정보 및 업로드 설정 |
임의 영역 업로드 |
| disabled | boolean |
false | 선택, 업로드 컴포넌트 비활성화 여부 | 업로드 금지 |
| droppable | boolean |
false | 선택, 드래그 지원 여부 | 파일 드래그 업로드 |
| multiple | boolean |
false | 선택, 다중 파일 선택 지원 여부 | 다중 파일 업로드 |
| upload-options | IUploadOptions | - | 선택, 업로드 설정 | 기본 사용법 |
| uploaded-files | Array<Object> |
- | 선택, 업로드된 파일 리스트 획득 | 기본 사용법 |
| on-success | function([{file, response}]) |
- | 선택, 파일 업로드 성공 시 훅 | 임의 영역 업로드 |
| on-error | function({file, response}) |
- | 선택, 파일 업로드 실패 시 훅 | 임의 영역 업로드 |
| on-exceed | function(files, uploadFiles) |
- | 선택, 파일 업로드 수가 제한 초과 시 훅 | 다중 파일 업로드 |
| on-change | function(files, uploadFiles) |
- | 선택, 파일 상태 변경 시 훅. 파일 추가, 업로드 성공, 업로드 실패 시 모두 호출 | 다중 파일 업로드 |
| on-progress | function(files, uploadFiles) |
- | 선택, 파일 업로드 시 훅 | 임의 영역 업로드 |
| on-preview | function(file) |
- | 선택, 파일 리스트의 파일 클릭 시 훅 | 다중 파일 업로드 |
| limit | number |
- | 선택, 업로드 가능 파일 최대 개수 | 다중 파일 업로드 |
| auto-upload | boolean |
true | 선택, 파일 선택 후 즉시 업로드 여부 | 수동 업로드와 비우기 |
| http-request | function(files) |
- | 선택, 기본 업로드 동작 대체. files는 선택한 파일 객체 리스트 | - |
Upload 이벤트
| 이벤트명 | 타입 | 설명 | Demo 링크 |
|---|---|---|---|
| delete-uploaded-file | (v: string) => void |
업로드 파일 삭제 콜백 함수. 삭제된 파일 경로 정보 반환 | 임의 영역 업로드 |
| file-drop | (v: any) => void |
드래그 업로드 지원 시 현재 드래그 파일 리스트 콜백. 단일 파일 업로드는 기본적으로 첫 번째 파일 반환 |
임의 영역 업로드 |
| file-over | (v: boolean) => void |
드래그 업로드 지원 시 파일이 드롭 가능 영역으로 이동할 때 트리거 이벤트. 드래그 가능 요소가 배치 대상에서 벗어나면 false 반환, 요소가 배치 대상으로 드래그 중이면 true 반환 |
임의 영역 업로드 |
| file-select | (v: File) => void |
파일 선택 후 콜백 함수. 선택된 파일 정보 반환 | 임의 영역 업로드 |
Upload 메서드
| 메서드명 | 설명 | Demo 링크 |
|---|---|---|
| submit | 수동으로 선택한 파일 업로드용 | 수동 업로드와 비우기 |
| clearFiles | 업로드된 파일과 선택된 파일 리스트 비우기용(before-upload 내 호출 미지원) | 수동 업로드와 비우기 |
Upload 슬롯
| 슬롯명 | 기본값 | 설명 | Demo 링크 |
|---|---|---|---|
| default | -- | 기본 콘텐츠 커스텀 | 임의 영역 업로드 |
| uploaded-files | -- | 선택, 커스텀 업로드 완료 파일 리스트 템플릿 생성용. 파라미터는 {uploadedFiles, deleteFile} |
임의 영역 업로드 |
Upload 타입 정의
IUploadOptions
export class IUploadOptions {
// 上传接口地址
uri: string;
// http 请求方法
method?: string;
// 上传文件大小限制
maximumSize?: number;
// 自定义请求headers
headers?: { [key: string]: any };
// 认证token
authToken?: string;
// 认证token header标示
authTokenHeader?: string;
// 上传额外自定义参数
additionalParameter?: { [key: string]: any };
// 上传文件字段名称,默认file
fileFieldName?: string;
// 多文件上传,是否检查文件重名,设置为true,重名文件不会覆盖,否则会覆盖上传
checkSameName?: boolean;
// 指示了是否该使用类似cookies,authorization headers(头部授权)或者TLS客户端证书这一类资格证书来创建一个跨站点访问控制(cross-site Access-Control)请求
withCredentials?: boolean;
// 手动设置返回数据类型
responseType?: 'arraybuffer' | 'blob' | 'json' | 'text';
}
더 알아보기 (Learn more)
upload-options로 업로드 주소와 헤더 등을 설정하고, 훅 함수로 업로드 과정을 세밀하게 제어할 수 있어요. 자세한 내용은 DevUI 공식 문서를 확인해 보세요.