使用JQuery调用SharePoint Rest API中的Batch命令批量添加,更新item

在SharePoint Framework中使用JQuery,调用SharePoint Rest API批量添加,更新item。这里使用Rest API中的Batch命令。

1, 创建项目

请参考这个微软官方文档创建SPFx项目: https://docs.microsoft.com/en-us/sharepoint/dev/spfx/web-parts/get-started/add-jqueryui-accordion-to-web-part

2, 修改UI,添加按钮和按钮事件。

public render(): void {
    this.domElement.innerHTML = `
      <div class="${ styles.demoCi }">
        <div class="${ styles.container }">
          <div class="${ styles.row }">
            <div class="${ styles.column }">
              <span class="${ styles.title }">Welcome to SharePoint!</span>
              <p class="${ styles.subTitle }">Customize SharePoint experiences using Web Parts.</p>
              <p class="${ styles.description }">${escape(this.properties.description)}</p>
              <div class="${ styles.row }">
                <span class="${styles.title}">Create items</span>
                <button class="${styles.button}" id="createButton"><span>Create</span></button>
              </div>
              <div class="${ styles.row }">
                <span class="${styles.title}">Update items</span>
                <button class="${styles.button}" id="updateButton"><span>Update</span></button>
              </div>
            </div>
          </div>
        </div>
      </div>`;
      
      this.bindButtonEvent();

  }

  private bindButtonEvent() {
    const webpart:DemoCiWebPart = this;
    this.domElement.querySelector("#createButton").addEventListener('click', ()=> {webpart.createNewItem();});
    this.domElement.querySelector("#updateButton").addEventListener('click', ()=> {webpart.updateItem();});
  }

3, 解决403 digist令牌问题

首先添加一个方法,做一个简单的JQuery调用Rest API的测试:

jQuery.ajax({
    url: this.context.pageContext.web.absoluteUrl + "/_api/web/lists/GetByTitle('MyTestList')",
    method: "POST",
    headers: { 
        "Accept": "application/json; odata=verbose", 
        "X-RequestDigest": jQuery('#__REQUESTDIGEST').val() 
    },
    success: function (data) {},
    error: function (data, errorCode, errorMessage) {}
});

启动gulp serve,在online工作台中添加并运行web part,会发现调用Rest API的时候,提示如下错误:

HTTP/1.1 403 FORBIDDEN
{"error":{"code":"-2130575252, Microsoft.SharePoint.SPException","message":{
"lang":"en-US",
"value":"The security validation for this page is invalid and might be corrupted. 
Please use your web browser's Back button to try your operation again."}}}

这是因为没有获取digist令牌的缘故( jQuery('#__REQUESTDIGIST').val() 返回undefined )。所以需要先使用如下代码获取令牌,然后再执行代码:


    jQuery.ajax({
        url: this.context.pageContext.web.absoluteUrl + "/_api/contextinfo",
        method: "POST",
        headers: { "Accept": "application/json; odata=verbose"},
        success: function (data) {
          const digist = data.d.GetContextWebInformation.FormDigestValue;
          //这里使用获取到的令牌
        },
        error: function (data, errorCode, errorMessage) {
            alert(errorMessage)
        }
    });

3, 批量处理添加和更新

private createNewItem() {
    const webpart : DemoCiWebPart = this;
    jQuery.ajax({
        url: this.context.pageContext.web.absoluteUrl + "/_api/contextinfo",
        method: "POST",
        headers: { "Accept": "application/json; odata=verbose"},
        success: function (data) {
          //jQuery('#__REQUESTDIGEST').val(data.d.GetContextWebInformation.FormDigestValue);
          webpart.CallAddRest(data.d.GetContextWebInformation.FormDigestValue);
        },
        error: function (data, errorCode, errorMessage) {
            alert(errorMessage)
        }
    });
  }

  private CallAddRest(digist) {
    let startDate = new Date();
    console.log(startDate.getMinutes() + '-' + startDate.getSeconds() + '-' + startDate.getMilliseconds());

    const batchGuid = this.generateUUID();
    const changeSetId = this.generateUUID();

    let batchContents = [];
    for(let i=1;i<50;i++)
    {
      const dataItem = 
        {
          '__metadata': {
            'type': 'SP.Data.MyTestListItem'
          },
          Index: i,
          BoolValue: true,
          TestStr: 'test 1 - ' + i,
          ChoiceOption: 'Starting',
          HoursStr: '2',
          Remarks: 'This is a test remarks - ' + i
        };

        let endpoint = this.context.pageContext.web.absoluteUrl + "/_api/web/lists/getByTitle('MyTest')/items";

        //changeset
        batchContents.push('--changeset_' + changeSetId);
        batchContents.push('Content-Type: application/http');
        batchContents.push('Content-Transfer-Encoding: binary');
        batchContents.push('');
        batchContents.push('POST ' + endpoint + ' HTTP/1.1');
        batchContents.push('Content-Type: application/json;odata=verbose');
        batchContents.push('');
        batchContents.push(JSON.stringify(dataItem));
        batchContents.push('');
    }

    batchContents.push('--changeset_' + changeSetId + '--');

    let batchBody = batchContents.join('\r\n');

    batchContents = new Array();

    batchContents.push('--batch_' + batchGuid);
    batchContents.push('Content-Type: multipart/mixed; boundary="changeset_' + changeSetId + '"');
    batchContents.push('Content-Length: ' + batchBody.length);
    batchContents.push('Content-Transfer-Encoding: binary');
    batchContents.push('');
    batchContents.push(batchBody);
    batchContents.push('');


    batchContents.push('--batch_' + batchGuid + '--');

    batchBody = batchContents.join('\r\n');

    console.log(batchBody);

    const batchEndPoint = this.context.pageContext.web.absoluteUrl + '/_api/$batch';
    const batchRequestHeader = {
      'X-RequestDigest': digist,
      'Content-Type': 'multipart/mixed; boundary="batch_' + batchGuid + '"'
    };

    jQuery.ajax({
        url: batchEndPoint,  //url
        type: "POST",
        headers: batchRequestHeader, 
        data: batchBody, 
        async: false,
        success: function (result) {
                console.log('Success!');
                let endDate = new Date();
                console.log(endDate.getMinutes() + '-' + endDate.getSeconds() + '-' + endDate.getMilliseconds());
                console.log(result);
            },
            error: function (error) {
              console.log('Error!');
                console.error(error.responseText);
            }
    });
  }

  private updateItem() { 
    const webpart : DemoCiWebPart = this;
    jQuery.ajax({
        url: this.context.pageContext.web.absoluteUrl + "/_api/contextinfo",
        method: "POST",
        headers: { "Accept": "application/json; odata=verbose"},
        success: function (data) {
          //jQuery('#__REQUESTDIGEST').val(data.d.GetContextWebInformation.FormDigestValue);
          webpart.CallUpdateRest(data.d.GetContextWebInformation.FormDigestValue);
        },
        error: function (data, errorCode, errorMessage) {
            alert(errorMessage)
        }
    });
  }

  private CallUpdateRest(digist) {
    console.log('inCall');
    let startDate = new Date();
    console.log(startDate.getMinutes() + '-' + startDate.getSeconds() + '-' + startDate.getMilliseconds());

    const batchGuid = this.generateUUID();
    const changeSetId = this.generateUUID();

    let batchContents = [];
    for(let i=1;i<51;i++)
    {
      const dataItem = 
        {
          '__metadata': {
            'type': 'SP.Data.MyTestListItem'
          },
          Index: i,
          BoolValue: true,
          TestStr: 'test 1 - ' + i,
          ChoiceOption: 'Starting',
          HoursStr: '2',
          Remarks: 'This is a test remarks - ' + i
        };

        let endpoint = this.context.pageContext.web.absoluteUrl + "/_api/web/lists/getByTitle('MyTest')/items("+i+")";

        //changeset
        batchContents.push('--changeset_' + changeSetId);
        batchContents.push('Content-Type: application/http');
        batchContents.push('Content-Transfer-Encoding: binary');
        batchContents.push('');
        batchContents.push('PATCH ' + endpoint + ' HTTP/1.1');
        batchContents.push('Content-Type: application/json;odata=verbose');
        batchContents.push('Accept: application/json;odata=verbose');
        batchContents.push('If-Match: *');
        batchContents.push('');
        batchContents.push(JSON.stringify(dataItem));
        batchContents.push('');
    }

    batchContents.push('--changeset_' + changeSetId + '--');

    let batchBody = batchContents.join('\r\n');

    batchContents = new Array();

    batchContents.push('--batch_' + batchGuid);
    batchContents.push('Content-Type: multipart/mixed; boundary="changeset_' + changeSetId + '"');
    batchContents.push('Content-Length: ' + batchBody.length);
    batchContents.push('Content-Transfer-Encoding: binary');
    batchContents.push('');
    batchContents.push(batchBody);
    batchContents.push('');


    batchContents.push('--batch_' + batchGuid + '--');

    batchBody = batchContents.join('\r\n');

    console.log(batchBody);

    const batchEndPoint = this.context.pageContext.web.absoluteUrl + '/_api/$batch';
    const batchRequestHeader = {
      'X-RequestDigest': digist,
      'Content-Type': 'multipart/mixed; boundary="batch_' + batchGuid + '"'
    };

    console.log('digist: ' + digist);
    jQuery.ajax({
        url: batchEndPoint, 
        type: "POST",
        headers: batchRequestHeader, 
        data: batchBody, 
        async: false,
        success: function (result) {
                console.log('Success!');
                let endDate = new Date();
                console.log(endDate.getMinutes() + '-' + endDate.getSeconds() + '-' + endDate.getMilliseconds());
                console.log(result);
            },
            error: function (error) {
              console.log('Error!');
                console.error(error.responseText);
            }
    });
  }

  private generateUUID() {
    var d = new Date().getTime();
    var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
      var r = (d + Math.random() * 16) % 16 | 0;
      d = Math.floor(d / 16);
      return (c == 'x' ? r : (r & 0x7 | 0x8)).toString(16);
    });
    return uuid;
  };

简单测评:

不同批量操作消耗的时间
  50 条数据 100条数据 200条数据
添加 10 秒左右 20 秒左右 30 秒左右
更新 3 秒左右 4 秒左右 11 秒左右

测试使用的表有6个列,每次添加和更新都是操作6个列。由此可见批量添加是非常耗时的,批量更新随着数据量变大,耗时会增加很快。如果批量更新200条数据,最好按批次更新,每次更新100条数据,会更省时间。

实际上使用JQuery调用Rest API是一种通用的方式,不局限于SharePoint Framework项目中。

在SharePoint Framework里,可以更方便地使用SPHttpClientBatch对象来实现上面的功能。请参见另一篇博客:在SharePoint Framework中使用SPHttpClientBatch对象批量添加,更新item

发布了189 篇原创文章 · 获赞 15 · 访问量 26万+

猜你喜欢

转载自blog.csdn.net/shrenk/article/details/91355576