Angular 2同步文件上传

时间:2017-03-20 13:51:47

标签: javascript angular typescript

我正在尝试将文件上传到web api,它使用angular 2应用程序将文件作为字节数组。

我无法将字符数组从角度2页面传递给web api。看起来File Reader读取方法是异步的。如何在执行下一行代码之前将其作为同步调用或等待加载文件内容?

以下是我的代码

//attachment on browse - when the browse button is clicked
//It only assign the file to a local variable (attachment)
fileChange = (event) => {
    var files = event.target.files;
    if (files.length > 0) {
        this.attachment = files[0];
    }
}

//when the submit button is clicked
onSubmit = () => {


        //Read the content of the file and store it in local variable (fileData)
        let fr = new FileReader();
        let data = new Blob([this.attachment]);
        fr.readAsArrayBuffer(data);
        fr.onloadend  = () => {
            this.fileData = fr.result; //Note : This always "undefined"
        };


        //build the attachment object which will be sent to Web API
        let attachment: Attachment = {
            AttachmentId: '0',
            FileName: this.form.controls["attachmentName"].value,
            FileData: this.fileData
        }

        //build the purchase order object
        let order: UpdatePurchaseOrder = {
            SendEmail: true,
            PurchaseOrderNumber: this.form.controls["purchaseOrderNumber"].value,
            Attachment: attachment
        }

        //call the web api and pass the purchaseorder object
        this.updatePoService
            .updatePurchaseOrder(this.form.controls["purchaseOrderRequestId"].value, order)
            .subscribe(data => {
                if (data) {
                    this.saveSuccess = true;
                }
                else {
                    this.saveSuccess = false;
                }
            },
                error => this.errors = error,
                () => this.res = 'Completed'
            );
    }

任何提示都会有用。

的问候, -Alan -

2 个答案:

答案 0 :(得分:2)

您无法使此异步调用同步。但是你可以利用observable来等待文件的读取:

//when the submit button is clicked
onSubmit = () => {
    let file = Observable.create((observer) => {
        let fr = new FileReader();
        let data = new Blob([this.attachment]);
        fr.readAsArrayBuffer(data);
        fr.onloadend = () => {
            observer.next(fr.result);
            observer.complete()
        };
        fr.onerror = (err) => {
            observer.error(err)
        }
        fr.onabort = () => {
            observer.error("aborted")
        }
    });
    file.map((fileData) => {
            //build the attachment object which will be sent to Web API
            let attachment: Attachment = {
                AttachmentId: '0',
                FileName: this.form.controls["attachmentName"].value,
                FileData: fileData
            }
            //build the purchase order object
            let order: UpdatePurchaseOrder = {
                SendEmail: true,
                PurchaseOrderNumber: this.form.controls["purchaseOrderNumber"].value,
                Attachment: attachment
            }
            return order;
        })
        .switchMap(order => this.updatePoService.updatePurchaseOrder(this.form.controls["purchaseOrderRequestId"].value, order))
        .subscribe(data => {
                if (data) {
                    this.saveSuccess = true;
                } else {
                    this.saveSuccess = false;
                }
            },
            error => this.errors = error,
            () => this.res = 'Completed'
        );
}

答案 1 :(得分:0)

我到达这里是为了寻找类似问题的解决方案。我正在执行对端点的请求,如果一切正常,它可以响应二进制Blob;如果发生错误,则可以返回JSON文件。

this.httpClient.post(urlService, bodyRequest,
      {responseType: 'blob', headers: headers})
.pipe(map((response: Response) => response), 
catchError((err: Error | HttpErrorResponse) => {
      if (err instanceof HttpErrorResponse) {
// here, err.error is a BLOB containing a JSON String with the error message
      } else {
        return throwError(ErrorDataService.overLoadError(err, message));
      }
}));

由于 FileReaderSync 在Angular6中显然不起作用,我采用n00dl3的解决方案(上述)在解析Blob内容后抛出错误:

return this.httpClient.post(urlService, bodyRequest,
      {responseType: 'blob', headers: headers})
.pipe(map((response: Response) => response), 
catchError((err: Error | HttpErrorResponse) => {
  const message = `In TtsService.getTts(${locale},${outputFormat}). ${err.message}`;
  if (err instanceof HttpErrorResponse) {
    const $errBlobReader: Observable<HttpErrorResponse> = Observable.create((observer) => {
      const fr = new FileReader();
      const errorBlob = err.error;
      fr.readAsText(errorBlob, 'utf8');
      fr.onloadend = () => {
        const errMsg =  JSON.parse(fr.result).message;
        const msg = `In TtsService.getTts(${locale},${outputFormat}). ${errMsg}`;
        observer.error(ErrorDataService.overLoadError(err, msg));
      };
      fr.onerror = (blobReadError) => {
        observer.error(blobReadError);
      };
      fr.onabort = () => {
        observer.error('aborted');
      };
    });
    return $errBlobReader;
  } else {
    return throwError(ErrorDataService.overLoadError(err, message));
  }
}));

谢谢!你真的救了我的一天!