问题
I'm using Microsoft Azure Storage Client Library's BlobService.createBlockBlobFromBrowserFile to allow users to upload files to an Azure Storage container. I'd like to provide a way for them to cancel an in-progress upload, e.g. in case it's big and taking too long or they chose the wrong file. Is there any way I can do this though? I can't see anything obvious in the API.
My code is based on these samples, e.g.
var file = document.getElementById('fileinput').files[0];
var customBlockSize = file.size > 1024 * 1024 * 32 ? 1024 * 1024 * 4 : 1024 * 512;
blobService.singleBlobPutThresholdInBytes = customBlockSize;
var finishedOrError = false;
var speedSummary = blobService.createBlockBlobFromBrowserFile('mycontainer', file.name, file, {blockSize : customBlockSize}, function(error, result, response) {
finishedOrError = true;
if (error) {
// Upload blob failed
} else {
// Upload successfully
}
});
refreshProgress();
The SpeedSummary
object returned from createBlockBlobFromBrowserFile
is I think this one, which doesn't have anything like that available.
Also asked on MSDN here.
回答1:
MSDN directed me to this github issue discussing the same question, and using a custom filter as a solution.
So here's my first attempt at a filter that lets you cancel an in-progress upload. This is certainly not perfect, but appears to work in my rudimentary testing. I'd love to get feedback from people actually familiar with this. Is this the right way to cancel, i.e. just return from within the callback?
I haven't tested it with any other filters applied, e.g. a retry filter. Also it assumes you only ever have one upload: it doesn't reset its state or expect multiple uploads.
// Filter allowing us to cancel an in-progress upload by setting 'cancel' to true.
// This doesn't cancel file chunks currently being uploaded, so the upload does continue
// for a while after this is triggered. If the last chunks have already been sent the
// upload might actually complete (??)
// See http://azure.github.io/azure-storage-node/StorageServiceClient.html#withFilter
var cancelUploadFilter = {
cancel: false, // Set to true to cancel an in-progress upload
loggingOn: true, // Set to true to see info on console
onCancelComplete: null, // Set to a function you want called when a cancelled request is (probably?) complete,
// i.e. when returnCounter==nextCounter. Because when you cancel an upload it can be many
// seconds before the in-progress chunks complete.
// Internal from here down
nextCounter: 0, // Increments each time next() is called. a.k.a. 'SentChunks' ?
returnCounter: 0, // Increments each time next()'s callback function is called. a.k.a. 'ReceivedChunks'?
handle: function (requestOptions, next) {
var self = this;
if (self.cancel) {
self.log('cancelling before chunk sent');
return;
}
if (next) {
self.nextCounter++;
next(requestOptions, function (returnObject, finalCallback, nextPostCallback) {
self.returnCounter++;
if (self.cancel) {
self.log('cancelling after chunk received');
if (self.nextCounter == self.returnCounter && self.onCancelComplete) {
self.onCancelComplete();
}
// REALLY ??? Is this the right way to stop the upload?
return;
}
if (nextPostCallback) {
nextPostCallback(returnObject);
} else if (finalCallback) {
finalCallback(returnObject);
}
});
}
},
log: function (msg) {
if (this.loggingOn) {
console.log('cancelUploadFilter: ' + msg + ' nc: ' + this.nextCounter + ', rc: ' + this.returnCounter);
}
},
};
You would use it when creating the blob service like this:
var blobService = azure.createBlobService().withFilter(cancelUploadFilter);
Then if you have an upload in progress you cancel it like so:
cancelUploadFilter.cancel = true;
// optional: if you want to know when all in-progress chunks have stopped:
cancelUploadFilter.onCancelComplete = function () { console.log('Cancelling complete'); };
来源:https://stackoverflow.com/questions/47762970/how-to-cancel-an-upload-started-with-blobservice-createblockblobfrombrowserfile