前言:
前期項目中使用了第三方的開源UI框架 View UI(前期叫 iView)。總體感覺該UI框架還是比較不錯的。但是現在View UI商業化了,部分功能需要付費才能使用。近期做的功能模塊需要上傳文件,就想到UI中的Upload上傳 模塊,思前想后決定用它來實現文件上傳。
之所以選用UI自身的文件上傳,主要是因為其可配置,還有上傳進度條。本次文件上傳因為要涉及到大文件上傳,上傳等待時間有點長,為了實時顯示上傳的進度,故采用Upload上傳,其自身帶有可配置的上傳進度條以及上傳文件列表,正好可以滿足我的需求。
需求:
此次文件上傳需要直傳遞(OSS)到阿里雲服務器。但是官方給的實例中,沒有涉及到OSS文件上傳的相關配置,為了達到實現OSS直傳的目的,現借助已有案例Demo來進一步的改寫,實現upload上傳文件到阿里雲服務器。
<Form ref="voteForm" :model="voteForm" :label-width="120">
<FormItem label="上傳附件">
<!-- 附件鏈接地址 -->
<input type="hidden" v-model.trim="voteForm.filePath" />
<!-- Upload上傳 -->
<Upload
:disabled="loading"
:action="upAction"
:data="upData"
:format="upFormat"
:before-upload="beforeUpload"
:on-success="onSuccess"
:on-error="onError"
:on-remove="onRemove"
:on-format-error="onFormatError"
:default-file-list="defaultFile"
>
<Button type="primary" icon="ios-cloud-upload-outline" :loading="loading">
{{ loading ? "上傳中..." : "上傳附件" }}
</Button>
</Upload>
<!-- 提示文字 -->
<p style="color:red;">溫馨提示:請上傳指定文件格式的文件!</p>
</FormItem>
</Form>
參數配置詳情:
屬性 | 說明 | 類型 | 默認值 |
---|---|---|---|
action | 上傳的地址,必填 | String | - |
disabled | 是否禁用 | Boolean | false |
data | 上傳時附帶的額外參數 | Object | - |
name | 上傳的文件字段名 | String | file |
show-upload-list | 是否顯示已上傳文件列表 | Boolean | true |
type | 上傳控件的類型,可選值為 select (點擊選擇),drag (支持拖拽) |
String | select |
accept | 接受上傳的文件類型 | String | - |
format | 支持的文件類型,與 accept 不同的是,format 是識別文件的后綴名,accept 為 input 標簽原生的 accept 屬性,會在選擇文件時過濾,可以兩者結合使用 | Array | [] |
before-upload | 上傳文件之前的鈎子,參數為上傳的文件,若返回 false 或者 Promise 則停止上傳 | Function | - |
on-success | 文件上傳成功時的鈎子,返回字段為 response, file, fileList | Function | - |
on-error | 文件上傳失敗時的鈎子,返回字段為 error, file, fileList | Function | - |
on-remove | 文件列表移除文件時的鈎子,返回字段為 file, fileList | Function | - |
on-format-error | 文件格式驗證失敗時的鈎子,返回字段為 file, fileList | Function | - |
on-exceeded-size | 文件超出指定大小限制時的鈎子,返回字段為 file, fileList | Function | - |
default-file-list | 默認已上傳的文件列表,例如:[{name: '',url: ''}] |
Array | [] |
【 oss.js 】文件:
const oss = {
accessKeyId: "" /* 用戶請求的accessid */ ,
accessKeySecret: "" /* */ ,
signature: "" /* 上傳文件簽名信息 */ ,
policy: "" /* 用戶表單上傳策略 */ ,
path: "https://xxxxxx.oss-cn-beijing.aliyuncs.com" /* 上傳阿里雲服務器地址 */ ,
filePath: "oss_file/" /* OSS上傳文件的路徑(生成指定的文件夾) */
};
/* 文件重命名 */
const fileRename = fileName => {
let suffixName = fileName;
if (fileName.lastIndexOf(".") != -1) {
suffixName = fileName.substring(fileName.lastIndexOf("."));
}
const moment = new Date();
let yyyy = moment.getFullYear(),
MM = moment.getMonth() + 1,
dd = moment.getDate(),
hh = moment.getHours(),
mm = moment.getMinutes(),
ss = moment.getSeconds();
MM = MM <= 9 ? "0" + MM : MM;
dd = dd <= 9 ? "0" + dd : dd;
let rm = (Math.random() * 1e5).toFixed(),
path = `${yyyy}${MM}/${dd}_${hh}${mm}${ss}_${rm}`;
return path + suffixName;
};
export { oss, fileRename };
注:提出全局公用的屬性和方法。
上傳文件屬性配置:
import { oss, fileRename } from "../utils/oss";
export default {
name: "Upload",
data() {
return {
loading: false,
defaultFile: [] /* { name: "", url: "" } */ ,
upAction: oss.path /* 上傳路徑 */ ,
upData: {
key: "" /* 文件路徑/文件名 */ ,
policy: "",
OSSAccessKeyId: "",
success_action_status: 200 /* 狀態碼 */ ,
signature: "",
name: "" /* 文件名 */
} /* 上傳參數 */ ,
upFormat: ["jpg", "jpeg", "png"] /* 上傳文件類型 */ ,
voteForm: {} /* form表單 */ ,
};
},
methods: {
// 上傳文件之前
beforeUpload(file) {
/* 文件重命名 */
let fileName = fileRename(String(file.name));
// 值傳參數
let {
accessKeyId,
policy,
signature,
filePath
} = oss;
Object.assign(this.upData, {
key: filePath[0] + fileName,
policy: policy,
OSSAccessKeyId: accessKeyId,
signature: signature,
name: fileName
});
this.loading = true;
},
// 上傳成功回調
onSuccess(response, file, fileList) {
this.loading = false;
// 拼接成完整的地址
let fileURI = this.upAction + "/" + this.upData.key;
this.voteForm.filePath = fileURI;
console.log("生成文件地址:", fileURI);
this.$Message.success({
background: true,
content: "文件上傳成功"
});
},
// 移除文件
onRemove(file) {
this.voteForm.filePath = "";
this.$Message.success({
background: true,
content: "附件移除成功"
});
},
// 文件上傳失敗
onError(error, file) {
this.loading = false;
this.$Message.error({
background: true,
content: "文件上傳失敗,請稍后再試!"
});
},
// 文件格式上傳失敗
onFormatError(file) {
// 上傳文件格式與指定文件格式不匹配
this.loading = false;
this.$Message.error({
background: true,
content: "上傳文件格式有誤,請重新選擇文件類型!"
});
}
}
};
注意事項:
- 此次項目中使用的是單文件上傳,如需配置多文件請參考官網API;
- 動態拼接上傳參數時需要提前給屬性賦默認值,在 beforeUpload 鈎子函數中做攔截處理;
- 在上傳文件之前獲取OSS直傳其它參數,進行賦值處理,否則上傳文件的參數只會展示一個默認的值 file;
- 在 beforeUpload函數中,若返回 false或者 Promise均會停止文件上傳;
- OSS直傳時 onSuccess 回調函數中 response 返回值 有可能為空,此時需要自己手動拼接上傳文件的絕對地址來進行賦值。