public async uploadPages()

in src/blob/handlers/PageBlobHandler.ts [167:264]


  public async uploadPages(
    body: NodeJS.ReadableStream,
    contentLength: number,
    options: Models.PageBlobUploadPagesOptionalParams,
    context: Context
  ): Promise<Models.PageBlobUploadPagesResponse> {
    const blobCtx = new BlobStorageContext(context);
    const accountName = blobCtx.account!;
    const containerName = blobCtx.container!;
    const blobName = blobCtx.blob!;
    const date = blobCtx.startTime!;

    if (contentLength % 512 !== 0) {
      throw StorageErrorFactory.getInvalidOperation(
        blobCtx.contextId!,
        "content-length or x-ms-content-length must be aligned to a 512-byte boundary."
      );
    }

    const blob = await this.metadataStore.downloadBlob(
      context,
      accountName,
      containerName,
      blobName,
      undefined,
      options.leaseAccessConditions
    );

    if (blob.properties.blobType !== Models.BlobType.PageBlob) {
      throw StorageErrorFactory.getBlobInvalidBlobType(blobCtx.contextId!);
    }

    // Check Lease status
    new BlobWriteLeaseValidator(options.leaseAccessConditions).validate(
      new BlobLeaseAdapter(blob),
      context
    );

    let ranges;
    try {
      ranges = deserializePageBlobRangeHeader(
        blobCtx.request!.getHeader("range"),
        blobCtx.request!.getHeader("x-ms-range"),
        true
      );
    } catch (err) {
      throw StorageErrorFactory.getInvalidPageRange(blobCtx.contextId!);
    }

    const start = ranges[0];
    const end = ranges[1]; // Inclusive
    if (end - start + 1 !== contentLength) {
      throw StorageErrorFactory.getInvalidPageRange(blobCtx.contextId!);
    }

    // Start Range is bigger than blob length
    if (start >= blob.properties.contentLength!) {
      throw StorageErrorFactory.getInvalidPageRange(blobCtx.contextId!);
    }

    const persistency = await this.extentStore.appendExtent(
      body,
      context.contextId
    );
    if (persistency.count !== contentLength) {
      // TODO: Confirm status code
      throw StorageErrorFactory.getInvalidOperation(
        blobCtx.contextId!,
        `The size of the request body ${persistency.count} mismatches the content-length ${contentLength}.`
      );
    }

    const res = await this.metadataStore.uploadPages(
      context,
      blob,
      start,
      end,
      persistency,
      options.leaseAccessConditions,
      options.modifiedAccessConditions,
      options.sequenceNumberAccessConditions
    );

    const response: Models.PageBlobUploadPagesResponse = {
      statusCode: 201,
      eTag: res.etag,
      lastModified: date,
      contentMD5: undefined, // TODO
      blobSequenceNumber: res.blobSequenceNumber,
      requestId: blobCtx.contextId,
      version: BLOB_API_VERSION,
      date,
      isServerEncrypted: true,
      clientRequestId: options.requestId
    };

    return response;
  }