Downloading file as PDF returns empty content

Vlad Vantaroo 20 Reputation points
2023-06-02T00:57:14.79+00:00

We are trying to download files from Sharepoint through the Graph API. Here is our code:

import { Response } from "node-fetch";


const contentStream = await client
  .api(`/sites/${siteId}/drive/items/${id}/content?format=pdf`)
  .getStream();
const response = new Response(contentStream);
const buffer = await response.buffer();

The response gives a status of 200, but the length of the buffer is only 23 (a successful download should have the buffer length be 32058). The API is not giving us any errors, so it is unclear why we are unable to download the file content.

Note that we are able to successfully fetch the item itself, just not the contents. For example, the following API call works fine:

const item = await client
  .api(`/sites/${siteId}/drive/items/${id}`)
  .get();

Any help would be great!

Microsoft Graph
Microsoft Graph
A Microsoft programmability model that exposes REST APIs and client libraries to access data on Microsoft 365 services.
11,319 questions
SharePoint
SharePoint
A group of Microsoft Products and technologies used for sharing and managing content, knowledge, and applications.
10,211 questions
{count} votes

Accepted answer
  1. ChengFeng - MSFT 5,020 Reputation points Microsoft Vendor
    2023-06-02T08:21:00.5933333+00:00

    Hi @Vlad Vantaroo

    From what you've provided, it looks like what's causing the problem is:

    Using the Response class from the node-fetch library to handle content streams can cause problems. This is because the Response class in node-fetch is primarily intended for handling HTTP response objects, not for handling content streams.

    The correct way is to convert the content stream directly to a buffer. Here it is suggested to customize the streamToBuffer function to convert the content stream into a buffer. This function collects chunks of the content stream into an array and concatenates the chunks at the end of the stream to form a buffer.

    By using the responseType('stream') method, we tell the Microsoft Graph client to return a readable stream in response. Then, we pass this readable stream to the streamToBuffer function for processing and get the final buffer.

    This approach handles the content stream correctly and converts it to the expected buffer, allowing you to successfully download the file content.

    Here is the code template for your reference:

    import { Readable } from 'stream';
    import fetch from 'node-fetch';
    
    async function makeGraphCallAsync(client, siteId, id) {
      const contentStream = await client
        .api(`/sites/${siteId}/drive/items/${id}/content?format=pdf`)
        .responseType('stream')
        .get();
    
      const buffer = await streamToBuffer(contentStream);
    
      console.log(buffer.length);
    }
    
    function streamToBuffer(stream) {
      const chunks = [];
      return new Promise((resolve, reject) => {
        stream.on('data', (chunk) => chunks.push(chunk));
        stream.on('error', reject);
        stream.on('end', () => resolve(Buffer.concat(chunks)));
      });
    }
    
    
    
    

    Here are some links for your reference:

    https://stackoverflow.com/questions/67169377/how-to-convert-fetch-response-to-array-buffer

    https://stackoverflow.com/questions/71377489/converting-response-to-arraybuffer


    If the answer is helpful, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    Best Regards

    Cheng Feng


0 additional answers

Sort by: Most helpful