token
上傳文件到文件服務器,上傳成功服務器返回體裏包含fileId
和fileName
,上傳失敗返回失敗code
,fileId
調接口獲取二進制流文件,根據fileName
的後綴獲取文件類型,把二進制文件根據文件類型生成文件。其餘邏輯html
解決方案;
使用el-upload
提供的header
便可ios
<el-upload :headers="headers" />
data(){ return { headers:{token:"111"} } }
判斷預覽時返回的二進制流,分狀況處理element-ui
handlePreview(file) { // console.log('要預覽的文件是:', file) // 獲取服務端返回的文件id和文件名 const fileId = file.response.body.fileId const fileName = file.response.body.fileName axios.post( this.DOWNLOAD_URL, { body: { fileId: fileId } }, { // 設置axios的headers和返回數據類型 headers: this.headers, responseType: 'blob' } ) .then(res => { // 若是文件未找到仍是可能會返回二進制格式的json信息,須要進行處理 // 正常狀況下會返回須要的二進制文件 if (this.handleMessage(res)) { // 處理正常狀況的二進制文件 var fileType = this.getFileType(fileName) if (fileType === 'image') { this.downImage(res.data, fileName) } else { console.info('非圖片格式暫沒法預覽') } } }) }, handleMessage(res) { // 未處理過的response對象,若是爲正常的二進制流文件返回true,若是爲二進制的json文件則返回false並展現json內容 if (res.data && res.data.type) { if (res.data.type === 'application/octet-stream') { // 正常的二進制流文件 return true } else if (res.data.type === 'application/json') { // 異常的二進制的JSON文件 const reader = new FileReader() reader.readAsText(res.data, 'utf-8') reader.onload = e => { const result = JSON.parse(reader.result) const message = '下載資源文件失敗' + reader.result console.error('下載資源文件失敗:', result) this.$message({ message: message, type: 'error', duration: 5 * 1000 }) } return false } } else { console.error( '函數入參response對象應該是一個完整的對象,應該包含data.type屬性' ) } }, getFileType(fileName) { // 更多文件類型 參考 https://www.cnblogs.com/zhongcj/archive/2008/11/03/1325293.html const arr = fileName.split('.') const len = arr.length let str = '' if (len > 1) { const allowedImageType = this.allowedImageType ||['jpg','jpeg','png'] const allowedVideoType = this.allowedVideoType || ['mp4'] const fileType = arr[arr.length - 1].toLocaleLowerCase() if (allowedImageType.includes(fileType)) { str = 'image' } else if (allowedVideoType.includes(fileType)) { str = 'video' } } return str }, downImage(blobData, fileName) { const blob = new Blob([blobData], { type: 'image/jpeg' }) const reader = new FileReader() reader.readAsDataURL(blob) reader.onload = e => { const url = URL.createObjectURL(blob) // 取到url,直接在頁面展現便可 } },
問題產生緣由: element-ui
裏upload
組件是根據httpCode
來判斷的,若是爲httpCode<200||httpCode>=300
則判斷爲上傳失敗,其餘狀況則標記爲上傳成功。json
而開發過程倒是不處理httpCode
而是根據responseBody
裏的code
字段進行判斷,雖然我也感受經過httpCode
更合適,可是碰到不少狀況都是經過響應體裏的code
來判斷的(難不成是由於後端同事不知道怎麼處理httpCode
?)axios
handleSuccess(res, file, fileList) { // 上傳成功函數的res是responseBody的body體 // 處理element-ui認爲上傳成功(他是經過httpCode爲200斷定爲成功的),實際上傳失敗狀況(經過responseBody判斷) if (res.code && res.code !== 0) { // 上傳不成功給出提示信息 this.$message({ message: res.message || 'error', type: 'error', duration: 5 * 1000 }) this.$nextTick(function() { // 移除上傳失敗的文件,code爲0即爲成功 const successFileList = fileList.filter(ele => { return ele.response.code + '' === '0' }) // 從新設置列表爲正確的列表 // this.fileList = successFileList // 假上傳成功時也須要進行一次處理 this.$emit('my-update', successFileList) }) } },
使用自定義的v-model
解決在組件最外層獲取已上傳的文件列表後端
// 自定義組件內,設置v-model export default { model: { prop: 'fileList', event: 'my-update', }, props: { // element-ui上傳組件的文件列表數組 fileList: { type: Array, default() { return [] }, }, }, methods: { // 監聽ele-upload的change事件 根據文檔僅添加文件、上傳成功和上傳失敗時都會被調用 handleChange(file, fileList) { // console.log('文件發生變化', file, fileList) this.$emit('my-update', fileList) }, // 刪除文件後須要同步觸發下事件 handleRemove(file, fileList) { const fileId = file.response.body.fileId // console.log('執行刪除事件,要刪除的文件id', fileId, fileList) const selectedFileList = fileList.filter(ele => { return fileId !== ele.response.body.fileId }) // console.log('刪除後文件列表:', selectedFileList) this.$emit('my-update', selectedFileList) }, // 同時假上傳成功時也須要進行一次處理 }, }
<!-- 父組件裏使用 --> <upload-box v-model="uploadFileList" />