Я пытаюсь создать сервис, который позволит мне:
- Загрузка файлов в хранилище BLOB-объектов Azure
- Прогресс возврата
- При неудачной повторной попытке
- При успешном звонке в мой сервис сохранить путь к файлу
Чтобы достичь этого, я начал, следуя этому руководству на Medium . Мне удалось сохранить файлы в хранилище и вернуть текущий прогресс.
Мои проблемы возникают, когда я хочу позвонить в службу с сохраненным путем к файлу.
Я посмотрел на следующее, чтобы попытаться понять, как этого добиться, но безуспешно отправка нескольких запросов http , документов rxjs выполнение последующих запросов http .
Я изо всех сил пытаюсь понять, как я превращаю примеры в то, что я могу использовать.
Обратите внимание, что я пытаюсь сделать AzureBlobStorageService повторно используемым, поэтому я не делаю второй HTTP-вызов в службе Azure, за который будет отвечать вызывающий абонент.
Ниже приведен мой код с комментариями, в которых я пытался добавить mergeMap или flatMap и т. Д., Но безуспешно. Я удалил эти ссылки, так как перепробовал так много вариантов, что я чувствую, что комментарии дают более четкое представление о том, чего я пытаюсь достичь
Загрузить компонент
this.uploadProgress$ = from(inputNode.files as FileList).pipe(
map(file => this._uploadService.updateCertificate(file)),
combineAll()
);
Служба загрузки
// this is where I would like to call my REST api when the file has uploaded to azure
updateCertificate(file: File): Observable<IUploadProgress> {
return this._azureBlobStorage
.uploadCertificateToBlobStorage(file, this.group)
.pipe(
map(
progress => this.mapProgress(file, progress)
),
// flatMap(x => this._httpClient.post('xcv', JSON.Stringify(sasToken.filename))) <--fail 1
)
.pipe(flatMap(x => this._httpClient.post('', JSON.stringify('')))); <-- fail 2
} // also tried merge map and a couple of others
private mapProgress(file: File, progress: number): IUploadProgress {
return {
filename: file.name,
progress: progress
};
}
Служба Azure BlobStorage
uploadCertificateToBlobStorage(file: File, group: string): Observable<number>
{
this.populateSasToken('/cert/' + group + '/' + file.name);
return this.uploadToBlobStorage(this.sasToken, file);
}
private populateSasToken(filename: string): void {
//create sasToken stuff
}
private uploadToBlobStorage(sasToken: ISasToken, file: File): Observable<number> {
const customBlockSize = this.getBlockSize(file);
const options = { blockSize: customBlockSize };
const blobService = this.createBlobService(sasToken.storageAccessToken, sasToken.storageUri);
blobService.singleBlobPutThresholdInBytes = customBlockSize;
return this.uploadFile(blobService, sasToken, file, options);
}
private createBlobService(sasToken: string, blobUri: string): IBlobService {
return this._blobStorage
.createBlobServiceWithSas(blobUri, sasToken)
.withFilter(new this._blobStorage.ExponentialRetryPolicyFilter());
}
// Need to change this to return a custom object with number and the sasToken.filename
// but when I change this return type and the return of the associated methods I errors, I can't see what i'm missing
private uploadFile(
blobService: IBlobService,
sasToken: ISasToken,
file: File,
options: { blockSize: number }
): Observable<number> {
return new Observable<number>(observer => {
const speedSummary = blobService.createBlockBlobFromBrowserFile(
sasToken.container,
sasToken.filename,
file,
options,
error => this.callback(error, observer)
);
speedSummary.on('progress', () => this.getProgress(speedSummary, observer, sasToken.filename));
}).pipe(
startWith(0),
distinctUntilChanged()
// retry(4) I think this will allow me to retry failed called to azure.
);
}
private getProgress(speedSummary: ISpeedSummary, observer: Subscriber<number>, fileName: string): void {
const progress = parseInt(speedSummary.getCompletePercent(2), 10);
observer.next(progress === 100 ? 99 : progress);
}
private callback(error: any, observer: Subscriber<number>): void {
if (error) {
console.log(error);
observer.error(error);
} else {
observer.next(100);
observer.complete();
}
}
================================
Изменения в загрузке файла
приведенные ниже причины
Тип Observable не присваивается типу Observable
================================
export class Xxx {
y: number;
x: string;
}
private uploadFile(
blobService: IBlobService,
sasToken: ISasToken,
file: File,
options: { blockSize: number }
): Observable<Xxx> {
return new Observable<Xxx>(observer => {
const speedSummary = blobService.createBlockBlobFromBrowserFile(
sasToken.container,
sasToken.filename,
file,
options,
error => this.callback(error, observer)
);
speedSummary.on('progress', () => this.getProgress(speedSummary, observer, sasToken.filename));
}).pipe(
startWith(0),
distinctUntilChanged(),
retry(4)
);
}
private getProgress(speedSummary: ISpeedSummary, observer: Subscriber<Xxx>, fileName: string): void {
const progress = parseInt(speedSummary.getCompletePercent(2), 10);
// observer.next(progress === 100 ? 99 : progress);
observer.next(new Xxx());
}
private callback(error: any, observer: Subscriber<Xxx>): void {
if (error) {
console.log(error);
observer.error(error);
} else {
// observer.next(100);
observer.next(new Xxx());
observer.complete();
}
}