klone
klone

Reputation: 2075

How to cancel Azure blob upload (multiple files)

Azure blob service allows us to pass a cancel filter which can be used to cancel an upload (Example: How to cancel an upload started with BlobService.createBlockBlobFromBrowserFile?). It works fine for an individual upload, but it doesn't work well for situations when client is trying to upload multiple files. The problem is that cancel filter is an attribute of service itself, not an individual upload, so cancelling one upload cancels all the uploads. Is there any way (via typescript/JavaScript client) to cancel one upload while letting others go undisturbed?

Upvotes: 4

Views: 2093

Answers (2)

Jim Xu
Jim Xu

Reputation: 23121

The package azure-storage is legacy. Now Microsoft suggest customers use the new sdk V12 @azure/storage-blob. if you use the new SDK, we can use AbortController to cancel one operation. For more details, please refer to here.

For example (I test it in angular application)

  1. install Azure storage SDk
npm install @azure/storage-blob @azure/abort-controller
  1. Add the following code in polyfills.ts
(window as any).global = window;
(window as any).process = require( 'process' );
(window as any).Buffer = require( 'buffer' ).Buffer;
  1. Html
<label class="btn btn-default">
  <input type="file"
       id="file"
       multiple
       (change)="onFileChange($event)">
</label>


<div *ngFor="let item of fileInfos" class="mb-2">
  <span>{{ item.file.name }}</span>
  <div class="progress">
    <div
      class="progress-bar progress-bar-info progress-bar-striped"
      role="progressbar"
      attr.aria-valuenow=" {{ item.value }}"
      aria-valuemin="0"
      aria-valuemax="100"
      [ngStyle]="{ width: item.value + '%' }"
    >
      {{ item.value }}%
    </div>
  </div>

  <button class="btn btn-primary"  (click)='item.upload()'>upload</button>
  <button class="btn btn-primary"  (click)='item.cancel()'>cancel</button>

</div>
  1. Define FileInfo calss
import {AbortController} from '@azure/abort-controller'
import {BlobServiceClient,AnonymousCredential} from  '@azure/storage-blob'

export class FileInfo{

    file : File
    value=0
    private  controller = new AbortController()
    constructor(message: File) {
        this.file = message;
      }

    async upload(){
        try {
            
        const blobServiceClient= new BlobServiceClient('https://<accountNmae>.blob.core.windows.net/?<sas token>',
new AnonymousCredential)

        const containerClient= blobServiceClient.getContainerClient('<>') 
        const blob= containerClient.getBlockBlobClient(this.file.name)
        console.log(`start uploading file ${this.file.name}`)
        const total =this.file.size
        await blob.uploadData(this.file,{
            abortSignal: this.controller.signal,
            blobHTTPHeaders:{blobContentType: this.file.type},
            blockSize: 4*1024*1024,
            onProgress : (ev) =>{
                console.log(`You have uploaded ${ev.loadedBytes} bytes`);
                this.value=Math.round(100 * ev.loadedBytes/ total);
            }
        })
        console.log(` upload file ${this.file.name} successfully`)
        } catch (error) {
            console.log(`cannot upload file ${this.file.name}, it return error ${error}`)
        }
        
    }

    cancel(){
        this.controller.abort()
        console.log(`cancel uploading file ${this.file.name}`) 
    }
}
  1. Component
...
fileInfos: Array<FileInfo> =[]
  onFileChange(event:any) {
   this.fileInfos=[]
    for (var i = 0; i < event.target.files.length; i++) { 
        var file =event.target.files[i]
       
        this.fileInfos.push( new FileInfo(file))
      }
  }

enter image description here enter image description here

Upvotes: 6

klone
klone

Reputation: 2075

I was able to make it work by creating multiple cancel filters and cancel just a specific cancel filter associated with the that file upload.

Upvotes: -1

Related Questions