qiniu-js
Version:
Javascript SDK for Qiniu Resource (Cloud) Storage AP
77 lines (63 loc) • 2.57 kB
text/typescript
import { CRC32 } from '../utils/crc32'
import { direct } from '../api'
import Base from './base'
export default class Direct extends Base {
protected async run() {
this.logger.info('start run Direct.')
const formData = new FormData()
if (this.putExtra.mimeType) {
// 通过 Blob.slice 设置 file part 的 Content-Type 为指定的 mimeType
const fileBlob = this.file.slice(0, this.file.size, this.putExtra.mimeType)
formData.append('file', fileBlob, this.putExtra.fname || this.file.name)
} else {
formData.append('file', this.file, this.putExtra.fname || this.file.name)
}
formData.append('token', this.token)
if (this.key != null) {
formData.append('key', this.key)
}
formData.append('fname', this.putExtra.fname)
if (this.config.checkByServer) {
const crcSign = await CRC32.file(this.file)
formData.append('crc32', crcSign.toString())
}
if (this.putExtra.customVars) {
this.logger.info('init customVars.')
const { customVars } = this.putExtra
Object.keys(customVars).forEach(key => formData.append(key, customVars[key].toString()))
this.logger.info('customVars inited.')
}
if (this.putExtra.metadata) {
this.logger.info('init metadata.')
const { metadata } = this.putExtra
Object.keys(metadata).forEach(key => formData.append(key, metadata[key].toString()))
}
this.logger.info('formData inited.')
const result = await direct(this.uploadHost!.getUrl(), formData, {
onProgress: data => {
this.updateDirectProgress(data.loaded, data.total)
},
onCreate: xhr => this.addXhr(xhr)
})
this.logger.info('Direct progress finish.')
this.finishDirectProgress()
return result
}
private updateDirectProgress(loaded: number, total: number) {
// 当请求未完成时可能进度会达到100,所以total + 1来防止这种情况出现
this.progress = { total: this.getProgressInfoItem(loaded, total + 1) }
this.onData(this.progress)
}
private finishDirectProgress() {
// 在某些浏览器环境下,xhr 的 progress 事件无法被触发,progress 为 null,这里 fake 下
if (!this.progress) {
this.logger.warn('progress is null.')
this.progress = { total: this.getProgressInfoItem(this.file.size, this.file.size) }
this.onData(this.progress)
return
}
const { total } = this.progress
this.progress = { total: this.getProgressInfoItem(total.loaded + 1, total.size) }
this.onData(this.progress)
}
}