1. 程式人生 > 實用技巧 >上傳進度條功能示例

上傳進度條功能示例

一、簡介
本文例項主要講述了ng-cli 與JS+html5實現非同步檔案上傳進度條顯示功能

二、ng-cli版本
使用了angular-cli、NG-ZORRO中的nz-upload

1)http.service.ts:

 /**
 * 請求主體可以為 urlencoding、JSON、FormData 的 POST 請求
* @param _url|string 請求地址
* @param _params|ParamsType 引數物件
* @param contentType|ContentType Post請求body編碼格式
* @param safeResponse|HttpResponseType 請求錯誤時的返回值
* @param userNotification|boolean 是否顯示操作提示彈框
* @param errorSource|string 引起錯誤的操作來源
*/
Post(_url: string, _params: ParamsType, contentType: PostContentType, safeResponse: HttpResponseType,
   userNotification: boolean = true, errorSource: string = '', useErrMsg: boolean = false): Observable<HttpResponseType> {
   const URL = this.URLPattern.test(_url) ? _url : environment.baseURL + _url;
   const contentTypeArray = [new HttpParams({ fromObject: _params }), _params, this.toFormData(_params)];
   let messageID = '';
   const headerParam = this.getLoginInfo();
if (userNotification) {
   messageID = this.message.loading('編輯中...', { nzDuration: 0 }).messageId;
}
 return this.httpClient.post(URL, contentTypeArray[contentType], {
   headers: new HttpHeaders(headerParam),
   reportProgress: true
}).pipe(
map((response: HttpResponseType) => {
   this.message.remove(messageID);
   if (response['code'] === 200) {
   this.message.success('編輯成功');
} else {
  this.message.error(useErrMsg ? response.msg : '編輯失敗');
}

return response;
}),
catchError(this.handleError(safeResponse, errorSource, messageID, '編輯'))
);
}

2)xxx.html:

<div class="upFiles">
<div class="spangrup">上傳配置檔案</div>
<div>
<nz-upload style="display: inline-block" nzType="drag" nzAction='{{fileUrlSite}}' [nzCustomRequest]="customReq">
<p class="ant-upload-drag-icon">
<i nz-icon nzType="upload"></i>
</p>
<p class="ant-upload-text">點選或將檔案拖拽到這裡上傳</p>
</nz-upload>
</div>
</div>

3)xxx.ts:

/**
* 上傳檔案模組
*/
import { HttpClient, HttpEvent, HttpEventType, HttpRequest, HttpResponse } from '@angular/common/http'; //需引入
customReq = (item: UploadXHRArgs) => {
const formData = new FormData();
formData.append('file', item.file as any);
const req = new HttpRequest('POST', item.action!, formData, {
reportProgress: true
});
return this.http.request(req).subscribe(
(event: HttpEvent<any>) => {
if (event.type === HttpEventType.UploadProgress) {
//console.log(event.total!);
if (event.total! > 0) {
(event as any).percent = (event.loaded / event.total!) * 100;
}
item.onProgress!(event, item.file!);
} else if (event instanceof HttpResponse) {
//console.log(event);
if (event.body.code !== 200) {
item.onError!('', item.file!);
this.message.error(event.body.msg);
} else {
item.onSuccess!(event.body, item.file!, event);
this.message.success('上傳成功');
}
}
},
err => {
//console.log(err);
item.onError!(err, item.file!);
}
);
}

4)頁面展示:

三、JS+html5版本

1)html:

<progress id="progressBar" value="0" max="100" style="width: 300px;"></progress>  //程序標籤
<span id="percentage"></span><span id="time"></span>
<br /><br />
<input type="file" id="file" name="myfile" />
<input type="button" onclick="UpladFile()" value="上傳" />
<input type="button" onclick="cancleUploadFile()" value="取消" />

2)js:

<script type="text/javascript">
let xhr;
let ot;//
let oloaded;
//上傳檔案方法
function UpladFile() {
let fileObj = document.getElementById("file").files[0]; // js 獲取檔案物件
let url = "http://192.168.108.24:30573/xxx/xxx/"; // 接收上傳檔案的後臺地址
let form = new FormData(); // FormData 物件
form.append("mf", fileObj); // 檔案物件

xhr = new XMLHttpRequest(); // XMLHttpRequest 物件

 xhr.open("post", url, true);                      //post方式,url為伺服器請求地址,true 該引數規定請求是否非同步處理。
xhr.onload = uploadComplete; //請求完成
xhr.onerror = uploadFailed; //請求失敗
xhr.upload.onprogress = progressFunction; //【上傳進度呼叫方法實現】
xhr.upload.onloadstart = function () { //上傳開始執行方法
ot = new Date().getTime(); //設定上傳開始時間
oloaded = 0; //設定上傳開始時,以上傳的檔案大小為0
};
xhr.send(form); //開始上傳,傳送form資料
}
//上傳進度實現方法,上傳過程中會頻繁呼叫該方法
function progressFunction(evt) {
let progressBar = document.getElementById("progressBar");
let percentageDiv = document.getElementById("percentage");
// event.total是需要傳輸的總位元組,event.loaded是已經傳輸的位元組。如果event.lengthComputable不為真,則event.total等於0
if (evt.lengthComputable) {//
progressBar.max = evt.total;
progressBar.value = evt.loaded;
percentageDiv.innerHTML = Math.round(evt.loaded / evt.total * 100) + "%";
}

let time = document.getElementById("time");
let nt = new Date().getTime(); //獲取當前時間
let pertime = (nt - ot) / 1000; //計算出上次呼叫該方法時到現在的時間差,單位為s
ot = new Date().getTime(); //重新賦值時間,用於下次計算
let perload = evt.loaded - oloaded; //計算該分段上傳的檔案大小,單位b
oloaded = evt.loaded; //重新賦值已上傳檔案大小,用以下次計算

//上傳速度計算
let speed = perload / pertime;//單位b/s
let bspeed = speed;
let units = 'b/s';//單位名稱
if (speed / 1024 > 1) {
speed = speed / 1024;
units = 'k/s';
}
if (speed / 1024 > 1) {
speed = speed / 1024;
units = 'M/s';
}
speed = speed.toFixed(1);
//剩餘時間
let resttime = ((evt.total - evt.loaded) / bspeed).toFixed(1);
time.innerHTML = ',速度:' + speed + units + ',剩餘時間:' + resttime + 's';
if (bspeed == 0)
time.innerHTML = '上傳已取消';
}
//上傳成功響應
function uploadComplete(evt) {
alert("上傳成功!");
}
//上傳失敗
function uploadFailed(evt) {
alert("上傳失敗!");
}
//取消上傳
function cancleUploadFile() {
xhr.abort();
}
</script>

注意:

若想用jQuery 中的ajax實現的話,jQuery的 ajax 方法沒有關於 progress 事件的操作,此時需要呼叫的XMLHttpRequest物件是指定progress 事件。XMLHttpRequest物件,傳送資料的時候,有一個progress事件,用來返回進度資訊。

它分成上傳和下載兩種情況
1)下載的progress事件屬於XMLHttpRequest物件
2)上傳的progress事件屬於XMLHttpRequest.upload物件。