Read/Write Files

Solid Pods can store regular files (e.g., PDFs, photos, etc.) in addition to storing structured data as Things and SolidDatasets (see Read/Write Structured Data to store structured data).

The solid-client library provides various file handling functions. Files are represented as Blobs. Like other data stored in a Solid Pod, each file is a Resource with a distinct URL, which may or may not include the file extension, (e.g., .jpg extension for an image file).

Required Access

The same access control mechanism applies to these files as applies to any other Resource in the Pod. As such, to perform file operations on restricted Resources (i.e., not open to the general public), the user must first authenticate as someone with the appropriate access. Then, to make authenticated requests, pass to the various read/write functions the authenticated Session’s fetch function. For more information on authentication, see Authentication.

Action

Required Access

Read a file.

Read access to the file.

To write a new file to a container.

Either Append or Write access to the Container, depending on the library’s function:

If the user only has Append access to the Container, you can only use saveFileInContainer() to save a new file.

If the user has Write access to the Container, you can use either saveFileInContainer() or overwriteFile() to save a new file.

To replace an existing file in a container.

Write access to the File.

To delete an existing file in a container.

Write access to the File.

Retrieve a File

To read a file, you can use getFile() to fetch the file content at the specified URL. The getFile() returns the content as a Blob. Once fetched, you can decode appropriately.

Note

To use getFile(), the user must have Read access for the file. For more information on user access, see Manage Access to Data.

The following example uses getFile() to read the specified files. The example assumes the user has the appropriate access.

// ... import statement for authentication, which includes the fetch function, is omitted for brevity.
import { getFile, isRawData, getContentType, getSourceUrl, } from "@inrupt/solid-client";

// ... Various logic, including login logic, omitted for brevity.

// Read file from Pod 
async function readFileFromPod(fileURL) {
  try {
    // file is a Blob (see https://developer.mozilla.org/docs/Web/API/Blob)
    const file = await getFile(
      fileURL,               // File in Pod to Read
      { fetch: fetch }       // fetch from authenticated session
    );

    console.log( `Fetched a ${getContentType(file)} file from ${getSourceUrl(file)}.`);
    console.log(`The file is ${isRawData(file) ? "not " : ""}a dataset.`);

  } catch (err) {
    console.log(err);
  }
}

The above example uses:

Note

You can use getFile() to retrieve a file that contains structured data. In this case, getContentType() on the returned Blob might return text/turtle; charset=UTF-8 if the user’s Pod server defaults to returning structured data in that format. The isRawData() on the Blob returns false.

Write a File

When writing a file to a Pod, you can:

Write a File to a Specific URL

To specify the file’s destination URL during the save, use overwriteFile(). To use overwriteFile(), pass it the following parameters:

File URL

The destination URL for the File. If a file already exists at that URL, the function overwrites the existing file.

Options object

An object that includes the following options:

{ contentType: <MIME type>, fetch: <fetch func> }

fetch

fetch function from an authenticated session if accessing restricted Resource (i.e., the general public cannot write file at the specified location). See Authenticate (Browser) or Authenticate (Node.js).

Optional if the general public can write files at the specified location.

contentType

Optional. MIME type.

Note

  • To use overwriteFile(), the user must have Write access to the Container. For more information on user access, see Manage Access to Data.

  • When saving the file to the destination URL, the Solid server creates any intermediate Container as needed.

The following example uses overwriteFile() to save the selected local files to the specified URL. The example assumes the user has the appropriate access.

// ... import statement for authentication, which includes the fetch function, is omitted for brevity.

import { overwriteFile, getSourceUrl } from "@inrupt/solid-client";

// ... Various logic, including login logic, omitted for brevity.

const MY_POD_URL = "https://example.com/mypod/";

// Upload selected files to Pod
function handleFiles() {
  const fileList = document.getElementById('fileinput').files;

  fileList.forEach(file => {
    writeFileToPod(file, `${MY_POD_URL}uploadedFiles/${file.name}`, fetch);
  });
}

// Upload File to the targetFileURL.
// If the targetFileURL exists, overwrite the file.
// If the targetFileURL does not exist, create the file at the location.
async function writeFileToPod(file, targetFileURL, fetch ) {
  try {
    const savedFile = await overwriteFile(  
      targetFileURL,                              // URL for the file.
      file,                                       // File
      { contentType: file.type, fetch: fetch }    // mimetype if known, fetch from the authenticated session
    );
    console.log(`File saved at ${getSourceUrl(savedFile)}`);

  } catch (error) {
    console.error(error);
  }
}

In the example, if the uploadedFiles Container does not exist when saving the file, the Solid server creates it to save the file to the specified URL.

Save a File into an Existing Container

To specify only the URL of the parent Container during the save, i.e., to let the Solid server determine the name of your file in the Container, use saveFileInContainer(). To use saveFileInContainer(), pass it the following parameters:

Container URL

The URL of the Container where you wish to place the file. The Container must already exist.

Options object

An object that includes the following options:

{ slug: <name>, contentType: <MIME type>, fetch: <fetch func> }

slug

Optional. The suggested file name. There is no guarantee that the Solid server will use the slug as the saved file name.

If the Solid server decides to use the slug as the file name but the slug matches an already existing file in the specified Container, the Solid server creates a new name for your file. That is, the function does not overwrite existing files.

fetch

fetch function from an authenticated session if accessing restricted Resource (i.e., the general public cannot add files to the specified Container). See Authenticate (Browser) or Authenticate (Node.js).

Optional if the general public can add files to the specified Container.

contentType

Optional. MIME type.

Note

  • To use saveFileInContainer(), the user must have Append or Write access to the Container. For more information on user access, see Manage Access to Data. See also Authentication.

  • With saveFileInContainer(), you do not control the name, and thus the URL, of your file. The Solid server may or may not use the suggested slug as the file name.

  • If the specified Container does not exist, the save operation fails.

The following example reads local files and uses saveFileInContainer() to save the files into the specified Container. The example assumes the user has the appropriate access.

// ... import statement for authentication, which includes the fetch function, is omitted for brevity.

import { saveFileInContainer, getSourceUrl } from "@inrupt/solid-client";

// ... Various logic, including login logic, omitted for brevity.

const MY_POD_URL = "https://example.com/mypod/";

// Upload selected files into Container
function handleFiles() {
  const fileList = document.getElementById('fileinput').files;

  fileList.forEach(file => {
    placeFileInContainer(file, `${MY_POD_URL}uploadedFiles/`);
  });
}

// Upload file into the targetContainer.
async function placeFileInContainer(file, targetContainerURL) {
  try {
    const savedFile = await saveFileInContainer(
      targetContainerURL,           // Container URL
      file,                         // File 
      { slug: file.name, contentType: file.type, fetch: fetch }
    );
    console.log(`File saved at ${getSourceUrl(savedFile)}`);
  } catch (error) {
    console.error(error);
  }
}

After saving the file, the example uses getSourceUrl on the returned file to determine the saved filename.

Delete a File

To delete a file, you can use deleteFile() to remove the file at the specified URL. To use deleteFile(), pass it the following parameters:

File URL

The URL of the file to delete.

Options object

An object that includes the following option:

{ fetch: <fetch func> }

fetch

fetch function from an authenticated session if deleting a restricted Resource (i.e., the general public cannot delete the specified File). See Authenticate (Browser) or Authenticate (Node.js).

Optional if the general public can delete the Resource.

Note

The user must have Write access to the File. For more information on user access, see Manage Access to Data. See also Authentication.

The following example uses deleteFile() to delete the specified file. The example assumes the user has the appropriate access.

// ... import statement for authentication, which includes the fetch function, is omitted for brevity.

import { deleteFile } from "@inrupt/solid-client";

// ... Various logic, including login logic, omitted for brevity.

try {
  // Delete the specified file from the Pod.
  await deleteFile(
    "https://example.com/some/boring/file",  // File to delete
    { fetch: fetch }                         // fetch function from authenticated session
  );
  console.log("Deleted::  https://example.com/some/boring/file");
} catch (err) {
  console.error(err);
}