Angular 7使用进度指示器上载到blob存储
我正在尝试创建一项服务,该服务将允许我:Angular 7使用进度指示器上载到blob存储,angular,http,rxjs,rxjs6,Angular,Http,Rxjs,Rxjs6,我正在尝试创建一项服务,该服务将允许我: 将文件上载到Azure blob存储 返回进度 重试失败时 成功后,请调用我的服务以保存文件路径 为了实现这一点,我从以下几点开始。我已经能够在存储器中保存文件并返回当前进度 当我想在保存文件路径的情况下调用我的服务时,就会出现问题 我已经看了以下内容,试图找出如何实现这一点,但没有任何成功 我正在努力理解我是如何将这些例子变成我可以使用的东西的 请注意,我正在尝试使azureBlobStorageService可重用,因此我不会在azure服务中进行第
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
};
}
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();
}
}
//当文件上载到azure时,我希望在这里调用我的REST api
updateCertificate(文件:file):可观察{
把这个还给我
.uploadCertificateToBlobStorage(文件,this.group)
.烟斗(
地图(
progress=>this.mapProgress(文件,进度)
),
//flatMap(x=>this._-httpClient.post('xcv',JSON.Stringify(sasToken.filename)))this._-httpClient.post('',JSON.Stringify('')){
const speedSummary=blobService.createBlockBlobFromBrowserFile(
sasToken.container,
sasToken.filename,
文件
选项,
error=>this.callback(错误,观察者)
);
speedSummary.on('progress',()=>this.getProgress(speedSummary,observer,sasToken.filename));
}).烟斗(
startWith(0),
distinctUntilChanged()
//重试(4)我想这将允许我重试失败的azure调用。
);
}
私有getProgress(speedSummary:ISpeedSummary,观察者:订阅者,文件名:字符串):void{
const progress=parseInt(speedSummary.getcompleteepercent(2),10);
下一步(进度===100?99:进度);
}
专用回调(错误:any,观察者:Subscriber):void{
如果(错误){
console.log(错误);
观察者错误(错误);
}否则{
观察员:下一个(100);
observer.complete();
}
}
================================
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();
}
}
上载文件的更改
原因如下
类型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();
}
}
导出类Xxx{
y:数字;
x:字符串;
}
私有上传文件(
blobService:IBlobService,
sasToken:ISasToken,
档案:档案,
选项:{blockSize:number}
):可见{
返回新的可观察对象(观察者=>{
const speedSummary=blobService.createBlockBlobFromBrowserFile(
sasToken.container,
sasToken.filename,
文件
选项,
error=>this.callback(错误,观察者)
);
speedSummary.on('progress',()=>this.getProgress(speedSummary,observer,sasToken.filename));
}).烟斗(
startWith(0),
distinctUntilChanged(),
重试(4)
);
}
私有getProgress(speedSummary:ISpeedSummary,观察者:订阅者,文件名:字符串):void{
const progress=parseInt(speedSummary.getcompleteepercent(2),10);
//下一步(进度===100?99:进度);
下一个(新的Xxx());
}
专用回调(错误:any,观察者:Subscriber):void{
如果(错误){
console.log(错误);
观察者错误(错误);
}否则{
//观察员:下一个(100);
下一个(新的Xxx());
observer.complete();
}
}
我用过
我已经有一段时间没有看这段代码了,但这里有一些代码片段可能会有所帮助
file.service.ts
import * as FileSaver from 'file-saver';
import { Injectable } from '@angular/core';
import { ProgressHttp, Progress } from "angular-progress-http";
import { RequestOptions, Headers, Response, ResponseContentType } from '@angular/http';
import { AuthHttp } from 'angular2-jwt';
import { Observable } from 'rxjs/Observable';
import { environment } from '../environments/environment';
@Injectable()
export class FileService {
constructor(private http: ProgressHttp, private authHttp: AuthHttp) { }
upload(url: string, files: File[], listener: (progress: Progress) => void): Observable<Response> {
let formData: FormData = new FormData();
files.forEach(file => {
if (file) {
formData.append('uploadFile', file, file.name);
}
});
let headers = new Headers();
headers.append('Authorization', `Bearer ${localStorage.getItem('token')}`);
let options = new RequestOptions({ headers: headers });
return this.http.withUploadProgressListener(listener).post(url, formData, options);
}
download(url: string, filename: string) {
let options = new RequestOptions(new Headers({ 'Content-Type': 'application/json' }));
options.responseType = ResponseContentType.Blob;
this.authHttp.get(url, options).subscribe(r => {
this.saveFileContent(r, filename);
});
}
private saveFileContent(res: Response, filename: string) {
let fileBlob = res.blob();
let blob = new Blob([fileBlob]);
FileSaver.saveAs(blob, filename);
}
}
import*作为“文件保护程序”中的文件保存程序;
从“@angular/core”导入{Injectable};
从“角度进度http”导入{ProgressHttp,Progress};
从'@angular/http'导入{RequestOptions,Header,Response,ResponseContentType};
从'angular2 jwt'导入{AuthHttp};
从“rxjs/Observable”导入{Observable};
从“../environments/environment”导入{environment};
@可注射()
导出类文件服务{
构造函数(私有http:ProgressHttp,私有authHttp:authHttp){}
上传(url:string,files:File[],侦听器:(进度:进度)=>void):可观察{
让formData:formData=newformdata();
files.forEach(文件=>{
如果(文件){
append('uploadFile',file,file.name);
}
});
let headers=新的headers();
append('Authorization','Bearer${localStorage.getItem('token')}`);
let options=newrequestoptions({headers:headers});
返回此.http.withUploadProgressListener(listener).post(url、formData、选项);
}
下载(url:string,文件名:string){
let options=newrequestoptions(新头({'Content-Type':'application/json'}));
options.responseType=ResponseContentType.Blob;
this.authHttp.get(url,选项).subscribe(r=>{
此.saveFileContent(r,文件名);
});
}
私有saveFileContent(res:Response,filename:string){
设fileBlob=res.blob();
设blob=newblob([fileBlob]);
FileSaver.saveAs(blob,文件名);
}
}
以及api端点操作
[Authorize(Roles = "Administrator"), HttpPost("AddFile/{id}")]
public async Task<IActionResult> AddFile(int id)
{
var files = Request.Form.Files;
if (files.Count > 0)
{
var sectionId = dbContext.Articles.Where(a => a.Id == id).Select(a => a.SectionId).Single();
using (var fileStream = files[0].OpenReadStream())
{
await fileService.SaveAsync($"sections/{sectionId}/articles/{id}/{files[0].FileName}", fileStream);
}
}
return Content("Ok");
}
[Authorize(Roles=“Administrator”),HttpPost(“AddFile/{id}”)]
公共异步任务AddFile(int-id)
{
var files=Request.Form.files;
如果(files.Count>0)
{
var sectionId=dbContext.Articles.Where(a=>a.Id==Id).Select(a=>a.sectionId.Single();
使用(var fileStream=files[0].OpenReadStream())