Krishna Ecrio
Krishna Ecrio

Reputation: 49

How do I append a blob file using @azure/storage-blob sdk ? (NodeJS)

My file "mainfile.json" in blob storage has the following content :

[
  { "name": "abc", "id": "01", "location": "random" },
  { "month": "Jan", "project": "50%", "training": "50%" },
]

The data I'm trying to add to it is this :

{"month": "Feb", "project":"60%", "training":"40%"}

I want it to be something like this :

[
  { "name": "abc", "id": "01", "location": "random" },
  { "month": "Jan", "project": "50%", "training": "50%" },
  {"month": "Feb", "project":"60%", "training":"40%"}
]

I'm using @azure/storage-blob sdk to carry out the same and here's my code below :

const blobServiceClient = require("./getCred");
const fs = require("fs");

async function appendBlob() {
  const containerClient =
    blobServiceClient.getContainerClient("containername");
  //gets the main content from a blob
  const blobClient = containerClient.getBlobClient("mainfile.json");
  //the new appended content gets written into this blob
  const blockBlobClient = containerClient.getBlockBlobClient("data.json");
  // the data that needs to be appended
  const data = fs.readFileSync("new-data.json", "utf-8", (err) => {
    if (err) {
      console.log("File not read");
    }
  });

  // Get blob content from position 0 to the end
  // In Node.js, get downloaded data by accessing downloadBlockBlobResponse.readableStreamBody
  const downloadBlockBlobResponse = await blobClient.download();
  const downloaded = (
    await streamToBuffer(downloadBlockBlobResponse.readableStreamBody)
  ).toString();
  const append = await appendingFile(downloaded, data);

  const uploadBlobResponse = await blockBlobClient.upload(
    append,
    append.length
  );
  console.log(
    `Uploaded block blob to testing.json successfully`,
    uploadBlobResponse.requestId
  );

  // [Node.js only] A helper method used to read a Node.js readable stream into a Buffer
  async function streamToBuffer(readableStream) {
    return new Promise((resolve, reject) => {
      const chunks = [];
      readableStream.on("data", (data) => {
        chunks.push(data instanceof Buffer ? data : Buffer.from(data));
      });
      readableStream.on("end", () => {
        resolve(Buffer.concat(chunks));
      });
      readableStream.on("error", reject);
    });
  }

  async function appendingFile(content, toBeAdded) {
    return new Promise((resolve, reject) => {
      let temp = content.concat(toBeAdded);
      console.log(temp);
      resolve(temp);
      reject(new Error("Error occurred"));
    });
  }
}

But I get the following as the output :

[
  {
    "name": "KK",
    "id": "01",
    "location": "chennai"
  },
  {
    "month": "December",
    "project": "50%",
    "training": "50%"
  }
]
{
  "month": "January",
  "adaptive-cards": "50%",
  "azure-func-app": "50%"
}

My entire approach could be wrong as I'm new to coding. Please help me with this. Thanks in advance.

Upvotes: 2

Views: 1546

Answers (1)

Gaurav Mantri
Gaurav Mantri

Reputation: 136196

There's nothing wrong with your code and it is working properly.

The issue is with your understanding of the blob storage. Azure storage blob (any kind of blob - block, append or page) does not really know if you are trying to add an element to a JSON array. For blob storage, it is simply a chunk of bytes.

What you would need to do is read the blob into a string, using JSON.parse to create a JSON array object and add the data to that object. Once you have that object, convert it back to string using JSON.stringify and reupload that string (i.e. overwrite the blob).

Upvotes: 2

Related Questions