Skip to content
This repository has been archived by the owner on Aug 28, 2024. It is now read-only.

Working With: Files

Tomi Tavela edited this page Apr 19, 2017 · 17 revisions

One of the more challenging tasks on the client side is working with SharePoint files, especially if they are large files. We have added some methods to the library to help and their use is outlined below.

Reading Files

Reading files from the client using REST is covered in the below examples. The important thing to remember is choosing which format you want the file in so you can appropriately process it. You can retrieve a file as Blob, Buffer, JSON, or Text. If you have a special requirement you could also write your own parser.

import pnp from "sp-pnp-js";

pnp.sp.web.getFileByServerRelativeUrl("/sites/dev/documents/file.avi").getBlob().then((blob: Blob) => {});

pnp.sp.web.getFileByServerRelativeUrl("/sites/dev/documents/file.avi").getBuffer().then((buffer: ArrayBuffer) => {});

pnp.sp.web.getFileByServerRelativeUrl("/sites/dev/documents/file.json").getJSON().then((json: any) => {});

pnp.sp.web.getFileByServerRelativeUrl("/sites/dev/documents/file.txt").getText().then((text: string) => {});

// all of these also work from a file object no matter how you access it
pnp.sp.web.getFolderByServerRelativeUrl("/sites/dev/documents").files.getByName("file.txt").getText().then((text: string) => {});

Adding Files

Likewise you can add files using one of two methods, add or addChunked. The second is appropriate for larger files, generally larger than 10 MB but this may differ based on your bandwidth/latency so you can adjust the code to use the chunked method. The below example shows getting the file object from an input and uploading it to SharePoint, choosing the upload method based on file size.

declare var require: (s: string) => any;

import { ConsoleListener, Web, Logger, LogLevel, ODataRaw } from "sp-pnp-js";
import { auth } from "./auth";
let $ = require("jquery");

let siteUrl = "https://318studios.sharepoint.com/sites/dev";

// comment this out for non-node execution
// auth(siteUrl);

Logger.subscribe(new ConsoleListener());
Logger.activeLogLevel = LogLevel.Verbose;

let web = new Web(siteUrl);

$(() => {
    $("#testingdiv").append("<button id='thebuttontodoit'>Do It</button>");

    $("#thebuttontodoit").on('click', (e) => {

        e.preventDefault();

        let input = <HTMLInputElement>document.getElementById("thefileinput");
        let file = input.files[0];

        // you can adjust this number to control what size files are uploaded in chunks
        if (file.size <= 10485760) {

            // small upload
            web.getFolderByServerRelativeUrl("/sites/dev/Shared%20Documents/test/").files.add(file.name, file, true).then(_ => Logger.write("done"));
        } else {

            // large upload
            web.getFolderByServerRelativeUrl("/sites/dev/Shared%20Documents/test/").files.addChunked(file.name, file, data => {

                Logger.log({ data: data, level: LogLevel.Verbose, message: "progress" });

            }, true).then(_ => Logger.write("done!"));
        }
    });
});

Update File Content

You can of course use similar methods to update existing files as shown below:

web.getFileByServerRelativeUrl("/sites/dev/documents/test.txt").setContent("New string content for the file.");

web.getFileByServerRelativeUrl("/sites/dev/documents/test.mp4").setContentChunked(file);

Advanced Upload Options

Both the addChunked and setContentChunked methods support options beyond just supplying the file content.

progress function

A method that is called each time a chunk is uploaded and provides enough information to report progress or update a progress bar easily. The method has the signature:

(data: ChunkedFileUploadProgressData) => void

The data interface is:

export interface ChunkedFileUploadProgressData {
    stage: "starting" | "continue" | "finishing";
    blockNumber: number;
    totalBlocks: number;
    chunkSize: number;
    currentPointer: number;
    fileSize: number;
}

chunkSize

This property controls the size of the individual chunks and is defaulted to 10485760 bytes (10 MB). You can adjust this based on your bandwidth needs - especially if writing code for mobile uploads or you are seeing frequent timeouts.

getItem

Added in 2.0.3

This method allows you to get the item associated with this file. You can optionally specify one or more select fields. The result will be merged with a new Item instance so you will have both the returned property values and chaining ability in a single object.

pnp.sp.web.getFolderByServerRelativeUrl("/sites/dev/Shared Documents/test").getItem().then(item => {

    console.log(item);
});

pnp.sp.web.getFolderByServerRelativeUrl("/sites/dev/Shared Documents/test").getItem("Title", "Modified").then(item => {

    console.log(item);
});

pnp.sp.web.getFolderByServerRelativeUrl("/sites/dev/Shared Documents/test").getItem().then(item => {

    // you can also chain directly off this item instance
    item.getCurrentUserEffectivePermissions().then(perms => {

        console.log(perms);
    });
});

You can also supply a generic typing parameter and the resulting type will be a union type of Item and the generic type parameter. This allows you to have proper intellisense and type checking.

// also supports typing the objects so your type will be a union type
pnp.sp.web.getFolderByServerRelativeUrl("/sites/dev/Shared Documents/test").getItem<{ Id: number, Title: string }>("Id", "Title").then(item => {

    // You get intellisense and proper typing of the returned object
    console.log(`Id: ${item.Id} -- ${item.Title}`);

    // You can also chain directly off this item instance
    item.getCurrentUserEffectivePermissions().then(perms => {

        console.log(perms);
    });
});
Clone this wiki locally