Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/http/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Angular 7使用进度指示器上载到blob存储_Angular_Http_Rxjs_Rxjs6 - Fatal编程技术网

Angular 7使用进度指示器上载到blob存储

Angular 7使用进度指示器上载到blob存储,angular,http,rxjs,rxjs6,Angular,Http,Rxjs,Rxjs6,我正在尝试创建一项服务,该服务将允许我: 将文件上载到Azure blob存储 返回进度 重试失败时 成功后,请调用我的服务以保存文件路径 为了实现这一点,我从以下几点开始。我已经能够在存储器中保存文件并返回当前进度 当我想在保存文件路径的情况下调用我的服务时,就会出现问题 我已经看了以下内容,试图找出如何实现这一点,但没有任何成功 我正在努力理解我是如何将这些例子变成我可以使用的东西的 请注意,我正在尝试使azureBlobStorageService可重用,因此我不会在azure服务中进行第

我正在尝试创建一项服务,该服务将允许我:

  • 将文件上载到Azure blob存储
  • 返回进度
  • 重试失败时
  • 成功后,请调用我的服务以保存文件路径
  • 为了实现这一点,我从以下几点开始。我已经能够在存储器中保存文件并返回当前进度

    当我想在保存文件路径的情况下调用我的服务时,就会出现问题

    我已经看了以下内容,试图找出如何实现这一点,但没有任何成功

    我正在努力理解我是如何将这些例子变成我可以使用的东西的

    请注意,我正在尝试使azureBlobStorageService可重用,因此我不会在azure服务中进行第二次HTTP调用,这将是调用方的责任

    下面是我的代码和注释,我曾尝试添加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
        };
      }
    
    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())