Azure 存储 javascript 客户端:如何使用 Ionic/Angular 跟踪上传进度?
Azure storage javascript client: how to track upload progress using Ionic/Angular?
在此 guideline 之后,我想通过将 progress
值设为 DOM 来跟踪上传进度。我还想在上传完成后在 DOM 中打印 'done'。有没有办法“订阅”SpeedSummary 以便我可以获得它的进度值?还有其他更推荐的方法吗?
我的代码:
var finishedOrError = false;
var speedSummary = blobService.createBlockBlobFromBrowserFile('input-data', filename, file, {blockSize : customBlockSize}, function(error, result, response) {
finishedOrError = true;
if (error) {
// Upload blob failed
alert('Problema: Volver a intentar o contactar al administrador');
} else {
// Upload successfully
alert('Subida Exitosa');
finish_upload();
return result;
}
});
speedSummary.on('progress', function () {
var process = speedSummary.getCompletePercent();
displayProcess(process);
})
var finish_upload = function(){
//TODO set upload finish process
//this.isUploading = false; DOESN'T WORK SINCE this is speedSummary in this context
}
var displayProcess = function(process){
//TODO set progress indicator
}
注意:我知道这个 implementation 但是在实现 uploadFile
函数时它给我一个错误。但更重要的是,我正在寻找更直接的实现方式。
注2:上面提到的错误是
No overload matches this call.
Overload 1 of 11, '(op1: UnaryFunction<Observable<number>, Observable<unknown>>, op2: UnaryFunction<Observable<unknown>, Observable<number>>): Observable<...>', gave the following error.
Argument of type 'Observable<number>' is not assignable to parameter of type 'UnaryFunction<Observable<number>, Observable<unknown>>'.
如果想在angular应用中上传blob时跟踪上传进度,可以使用新的nodejs存储sdk@azure/storage-blob
来实现。
例如
- 创建一个 angular 网络应用程序
ng new <appname>
- 安装 Azure 存储 SDK
npm install @azure/storage-blob
- 更新app.component.html文件
<div class="mainContainer">
<div class="content">
<div class="header">
<h1>Angular File Upload</h1>
</div>
<div class="form-group">
<label for="file">Choose File</label>
<input type="file"
id="file"
(change)="onFileChange($event)">
<p> progress is = {{progress}} </p>
<p>result: {{status}}</p>
</div>
</div>
</div>
- 在polyfills.ts
中添加如下代码
(window as any).global = window;
(window as any).process = require( 'process' );
(window as any).Buffer = require( 'buffer' ).Buffer;
- 在app.component.ts
中添加如下代码
import { Component } from '@angular/core';
import {BlobServiceClient,AnonymousCredential,newPipeline } from '@azure/storage-blob';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'web1';
currentFile : File =null;
onFileChange(event) {
this.currentFile = event.target.files[0];
this.upload();
}
async upload(){
const accountName ="andyprivate";
const sasToken="";
const containerName="test";
const pipeline =newPipeline (new AnonymousCredential(),{
retryOptions: { maxTries: 4 }, // Retry options
userAgentOptions: { userAgentPrefix: "AdvancedSample V1.0.0" }, // Customized telemetry string
keepAliveOptions: { enable: false}
});
const blobServiceClient =new BlobServiceClient(`https://${accountName}.blob.core.windows.net?${sasToken}`,
pipeline )
const containerClient =blobServiceClient.getContainerClient(containerName)
if(!containerClient.exists()){
console.log("the container does not exit")
await containerClient.create()
}
const client = containerClient.getBlockBlobClient(this.currentFile.name)
await client.uploadBrowserData(this.currentFile,{
blockSize: 4 * 1024 * 1024, // 4MB block size
concurrency: 20, // 20 concurrency
onProgress: (ev) => {
console.log(`you have upload ${ev.loadedBytes} bytes`);
this.progress= (ev.loadedBytes/this.currentFile.size)*100;
},
blobHTTPHeaders :{blobContentType:this.currentFile.type}
}).then(response =>{
console.log(response)
if(response.errorCode !=null){
console.log("failed")
this.status="fail";
}
this.status="done";
})
}
}
- 通过 Azure 门户在 Azure 存储帐户中配置 CORS。详情请参考document
Allowed origins: *
Allowed verbs: DELETE,GET,HEAD,MERGE,POST,OPTIONS,PUT
Allowed headers: *
Exposed headers: *
Maximum age (seconds): 86400
- 测试
这就是我使用当前库对我有用的方法(另请注意 Jim Xu 对最新库的解决方案的回答)
async uploadFileToAzure(file, filename, index){
this.AStorage.getSAS(this.token, {"filename":filename}).subscribe(async sas=>{
var self = this;
this.sas = sas;
var blobUri = 'https://xxxx.blob.core.windows.net/'; //actual blobUri goes here
var blobService = AzureStorage.Blob.createBlobServiceWithSas(blobUri, this.sas["token"]);
var customBlockSize = file.size > 1024 * 1024 * 32 ? 1024 * 1024 * 4 : 1024 * 512;
blobService.singleBlobPutThresholdInBytes = customBlockSize;
var finishedOrError = false;
var self = this;
var speedSummary = blobService.createBlockBlobFromBrowserFile('input-data', filename, file, {blockSize : customBlockSize}, function(error, result, response) {
finishedOrError = true;
if (error) {
// Upload blob failed
self.show_toast('Problema: Volver a intentar o contactar al administrador');
} else {
// Upload successfully
self.show_toast('Subida Exitosa');
finish_upload();
return result;
}
});
speedSummary.on('progress', function () {
var process = speedSummary.getCompletePercent();
displayProcess(process);
})
var finish_upload = function(){
//TODO: set upload finish process
}
var file_to_process = this.files_to_process[index]
var displayProcess = function(process){
console.log('file_to_process', file_to_process)
var s = document.getElementById(file_to_process)
s.innerHTML = process;
//var s = document.getElementById(progress_bars[index])
}
});
}
在此 guideline 之后,我想通过将 progress
值设为 DOM 来跟踪上传进度。我还想在上传完成后在 DOM 中打印 'done'。有没有办法“订阅”SpeedSummary 以便我可以获得它的进度值?还有其他更推荐的方法吗?
我的代码:
var finishedOrError = false;
var speedSummary = blobService.createBlockBlobFromBrowserFile('input-data', filename, file, {blockSize : customBlockSize}, function(error, result, response) {
finishedOrError = true;
if (error) {
// Upload blob failed
alert('Problema: Volver a intentar o contactar al administrador');
} else {
// Upload successfully
alert('Subida Exitosa');
finish_upload();
return result;
}
});
speedSummary.on('progress', function () {
var process = speedSummary.getCompletePercent();
displayProcess(process);
})
var finish_upload = function(){
//TODO set upload finish process
//this.isUploading = false; DOESN'T WORK SINCE this is speedSummary in this context
}
var displayProcess = function(process){
//TODO set progress indicator
}
注意:我知道这个 implementation 但是在实现 uploadFile
函数时它给我一个错误。但更重要的是,我正在寻找更直接的实现方式。
注2:上面提到的错误是
No overload matches this call.
Overload 1 of 11, '(op1: UnaryFunction<Observable<number>, Observable<unknown>>, op2: UnaryFunction<Observable<unknown>, Observable<number>>): Observable<...>', gave the following error.
Argument of type 'Observable<number>' is not assignable to parameter of type 'UnaryFunction<Observable<number>, Observable<unknown>>'.
如果想在angular应用中上传blob时跟踪上传进度,可以使用新的nodejs存储sdk@azure/storage-blob
来实现。
例如
- 创建一个 angular 网络应用程序
ng new <appname>
- 安装 Azure 存储 SDK
npm install @azure/storage-blob
- 更新app.component.html文件
<div class="mainContainer">
<div class="content">
<div class="header">
<h1>Angular File Upload</h1>
</div>
<div class="form-group">
<label for="file">Choose File</label>
<input type="file"
id="file"
(change)="onFileChange($event)">
<p> progress is = {{progress}} </p>
<p>result: {{status}}</p>
</div>
</div>
</div>
- 在polyfills.ts 中添加如下代码
(window as any).global = window;
(window as any).process = require( 'process' );
(window as any).Buffer = require( 'buffer' ).Buffer;
- 在app.component.ts 中添加如下代码
import { Component } from '@angular/core';
import {BlobServiceClient,AnonymousCredential,newPipeline } from '@azure/storage-blob';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'web1';
currentFile : File =null;
onFileChange(event) {
this.currentFile = event.target.files[0];
this.upload();
}
async upload(){
const accountName ="andyprivate";
const sasToken="";
const containerName="test";
const pipeline =newPipeline (new AnonymousCredential(),{
retryOptions: { maxTries: 4 }, // Retry options
userAgentOptions: { userAgentPrefix: "AdvancedSample V1.0.0" }, // Customized telemetry string
keepAliveOptions: { enable: false}
});
const blobServiceClient =new BlobServiceClient(`https://${accountName}.blob.core.windows.net?${sasToken}`,
pipeline )
const containerClient =blobServiceClient.getContainerClient(containerName)
if(!containerClient.exists()){
console.log("the container does not exit")
await containerClient.create()
}
const client = containerClient.getBlockBlobClient(this.currentFile.name)
await client.uploadBrowserData(this.currentFile,{
blockSize: 4 * 1024 * 1024, // 4MB block size
concurrency: 20, // 20 concurrency
onProgress: (ev) => {
console.log(`you have upload ${ev.loadedBytes} bytes`);
this.progress= (ev.loadedBytes/this.currentFile.size)*100;
},
blobHTTPHeaders :{blobContentType:this.currentFile.type}
}).then(response =>{
console.log(response)
if(response.errorCode !=null){
console.log("failed")
this.status="fail";
}
this.status="done";
})
}
}
- 通过 Azure 门户在 Azure 存储帐户中配置 CORS。详情请参考document
Allowed origins: *
Allowed verbs: DELETE,GET,HEAD,MERGE,POST,OPTIONS,PUT
Allowed headers: *
Exposed headers: *
Maximum age (seconds): 86400
- 测试
这就是我使用当前库对我有用的方法(另请注意 Jim Xu 对最新库的解决方案的回答)
async uploadFileToAzure(file, filename, index){
this.AStorage.getSAS(this.token, {"filename":filename}).subscribe(async sas=>{
var self = this;
this.sas = sas;
var blobUri = 'https://xxxx.blob.core.windows.net/'; //actual blobUri goes here
var blobService = AzureStorage.Blob.createBlobServiceWithSas(blobUri, this.sas["token"]);
var customBlockSize = file.size > 1024 * 1024 * 32 ? 1024 * 1024 * 4 : 1024 * 512;
blobService.singleBlobPutThresholdInBytes = customBlockSize;
var finishedOrError = false;
var self = this;
var speedSummary = blobService.createBlockBlobFromBrowserFile('input-data', filename, file, {blockSize : customBlockSize}, function(error, result, response) {
finishedOrError = true;
if (error) {
// Upload blob failed
self.show_toast('Problema: Volver a intentar o contactar al administrador');
} else {
// Upload successfully
self.show_toast('Subida Exitosa');
finish_upload();
return result;
}
});
speedSummary.on('progress', function () {
var process = speedSummary.getCompletePercent();
displayProcess(process);
})
var finish_upload = function(){
//TODO: set upload finish process
}
var file_to_process = this.files_to_process[index]
var displayProcess = function(process){
console.log('file_to_process', file_to_process)
var s = document.getElementById(file_to_process)
s.innerHTML = process;
//var s = document.getElementById(progress_bars[index])
}
});
}