Files
element-plus/packages/components/upload/src/ajax.ts
arvin 5c1306127f fix(components): [upload] fix empty array error (#13490)
* fix(components): [upload] fix empty array error

在 components/upload/src/ajax.ts 73 行中,如果data 中key对应的value 是空数组的情况下`if (Array.isArray(value)) formData.append(key, ...value)`报错

* fix: reuse isArray

---------

Co-authored-by: btea <2356281422@qq.com>
2023-08-13 10:23:06 +08:00

109 lines
2.6 KiB
TypeScript

import { isNil } from 'lodash-unified'
import { isArray, throwError } from '@element-plus/utils'
import type {
UploadProgressEvent,
UploadRequestHandler,
UploadRequestOptions,
} from './upload'
const SCOPE = 'ElUpload'
export class UploadAjaxError extends Error {
name = 'UploadAjaxError'
status: number
method: string
url: string
constructor(message: string, status: number, method: string, url: string) {
super(message)
this.status = status
this.method = method
this.url = url
}
}
function getError(
action: string,
option: UploadRequestOptions,
xhr: XMLHttpRequest
) {
let msg: string
if (xhr.response) {
msg = `${xhr.response.error || xhr.response}`
} else if (xhr.responseText) {
msg = `${xhr.responseText}`
} else {
msg = `fail to ${option.method} ${action} ${xhr.status}`
}
return new UploadAjaxError(msg, xhr.status, option.method, action)
}
function getBody(xhr: XMLHttpRequest): XMLHttpRequestResponseType {
const text = xhr.responseText || xhr.response
if (!text) {
return text
}
try {
return JSON.parse(text)
} catch {
return text
}
}
export const ajaxUpload: UploadRequestHandler = (option) => {
if (typeof XMLHttpRequest === 'undefined')
throwError(SCOPE, 'XMLHttpRequest is undefined')
const xhr = new XMLHttpRequest()
const action = option.action
if (xhr.upload) {
xhr.upload.addEventListener('progress', (evt) => {
const progressEvt = evt as UploadProgressEvent
progressEvt.percent = evt.total > 0 ? (evt.loaded / evt.total) * 100 : 0
option.onProgress(progressEvt)
})
}
const formData = new FormData()
if (option.data) {
for (const [key, value] of Object.entries(option.data)) {
if (isArray(value) && value.length) formData.append(key, ...value)
else formData.append(key, value)
}
}
formData.append(option.filename, option.file, option.file.name)
xhr.addEventListener('error', () => {
option.onError(getError(action, option, xhr))
})
xhr.addEventListener('load', () => {
if (xhr.status < 200 || xhr.status >= 300) {
return option.onError(getError(action, option, xhr))
}
option.onSuccess(getBody(xhr))
})
xhr.open(option.method, action, true)
if (option.withCredentials && 'withCredentials' in xhr) {
xhr.withCredentials = true
}
const headers = option.headers || {}
if (headers instanceof Headers) {
headers.forEach((value, key) => xhr.setRequestHeader(key, value))
} else {
for (const [key, value] of Object.entries(headers)) {
if (isNil(value)) continue
xhr.setRequestHeader(key, String(value))
}
}
xhr.send(formData)
return xhr
}