我正在尝试向SharePoint列表项添加多个附件。服务方法接受附件列表,只有在上传所有文件后才返回响应(Sharepoint API一次只接受一个文件(。所以我使用rxjs forkJoin来达到这个目的。
下面是我写的服务课程。
import { Injectable } from '@angular/core';
import { Observable, forkJoin } from 'rxjs';
import { HttpClient, HttpHeaders } from '@angular/common/http'
import { ContextService } from './context.service'
import { mergeMap } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class AttachmentService {
constructor(private httpClient: HttpClient) { }
addAttachmentsToTheList(listName: string, listItemId: number, attachmentList: any[], diagest: any) {
//get the file upload observable list
let fileUploadOnservables: any[] = [];
attachmentList.forEach(file => {
fileUploadOnservables.push(this.addAttachment(listName, listItemId, file, diagest))
});
// use forkJoin to combine the operations and subscribe to all results
// use forkJoin to combine the operations and subscribe to all results
forkJoin(fileUploadOnservables)
.subscribe(
(response) => {
//after all the successful requests do something
}
);
}
}
//this will add a single attachment to list
addAttachment(listName: string, listItemId: number, file: any, diagest: any) {
//first read the file as buffer, and pass the buffer to the Sharepoint REST API
return this.getFileBuffer(file)
.pipe(
mergeMap((fileBuffer: any) => {
//once file buffer observable returns pass the buffer to the Sharepoint REST API
return this.httpClient.post(
"../_api/lists/GetByTitle('" + listName + "')/items(" + listItemId + ")/AttachmentFiles/add(FileName='" + file.name + "')",
fileBuffer,
{
headers: new HttpHeaders({
'X-RequestDigest': diagest,
'Accept': 'application/json; odata=verbose',
'Content-Type': 'application/json; odata=verbose'
})
})
})
);
}
//this returns the file buffer
getFileBuffer(file) {
return new Observable(subscriber => {
var reader = new FileReader();
reader.readAsArrayBuffer(file);
reader.onload = function (e: any) {
subscriber.next(e.target.result);
subscriber.complete();
};
});
}
}
组件内:
someMethod(){
this.attachmentService.addAttachmentsToTheList('SomeList', 1, this.attachmentList,diagest)
.subscribe(
(result: any) => {
//do something
},
(error: any) => {
//handle error
});
}
这段代码抛出以下错误,但它也会上传文件。我在这里做错了什么,如何修复这个错误?
Cannot read property 'subscribe' of undefined
感谢你的帮助。
原始答案
看起来错误是由您从组件订阅服务中方法的结果引起的,但是服务中的方法实际上并没有向组件返回任何内容。您应该能够通过从服务中的方法返回forkJoin
的结果并将subscribe()
从服务中方法移动到组件来解决此错误。我建议在方法中添加返回类型,因为这将有助于在将来更好地捕捉类似于此的错误。
addAttachmentsToTheList(listName: string, listItemId: number, attachmentList: any[], diagest: any): Observable<...> {
//get the file upload observable list
let fileUploadOnservables: any[] = [];
attachmentList.forEach(file => {
fileUploadOnservables.push(this.addAttachment(listName, listItemId, file, diagest))
});
// use forkJoin to combine the operations and subscribe to all results
return forkJoin(fileUploadOnservables);
}
如果您在分叉加入fileUploadOnservables
之后需要在服务中执行进一步的操作,那么您可以使用pipe
函数:
return forkJoin(fileUploadOnservables).pipe(...);
更新的答案
您可以尝试使用from
运算符将值列表拆分为单独的事件,然后使用toArray
运算符组合每个事件。
addAttachmentsToTheList(listName: string, listItemId: number, attachmentList: any[], diagest: any): Observable<...> {
return from(attachmentList).pipe(mergeMap(value => this.addAttachment(listName, listItemId, value, diagest)), toArray());
}