> ## Documentation Index
> Fetch the complete documentation index at: https://pipedream.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# File Stores Node.js Reference

The File Stores Node.js helper allows you to manage files within Code Steps and Action components.

## `$.files`

The `$.files` helper is the main module to interact with the Project’s File Store. It can instantiate new files, open files from descriptors and list the contents of the File Store.

### `$.files.open(path)`

*Sync.* Opens a file from the relative `path`. If the file doesn’t exist, a new empty file is created.

### `$.files.openDescriptor(fileDescriptor)`

*Sync.* Creates a new `File` from the JSON friendly description of a file. Useful for recreating a `File` from a step export.

For example, export a `File` as a step export which will render the `File` as JSON:

```javascript theme={null}
// create_file
// Creates a new Project File and uploads an image to it
export default defineComponent({
  async run({ steps, $ }) {
    // create the new file and upload the contents to it from a URL
    const file = await $.files.open("imgur.png").fromUrl("https://i.imgur.com/TVIPgNq.png")
    // return the file as a step export
    return file
  },
}
```

Then in a downstream step recreate the `File` instance from the step export friendly *description*:

```javascript theme={null}
// download_file
// Opens a file downloaded from a previous step, and saves it.
export default defineComponent({
  async run({ steps, $ }) {
    // Convert the the description of the file back into a File instance
    const file = $.files.openDescriptor(steps.create_file.$return_value)
    // Download the file to the local /tmp directory
    await $.file.download('/tmp/example.png')
    console.log("File downloaded to /tmp")
  },
})
```

### `$.files.dir(?path)`

*Sync.* Lists the files & directories at the given `path`. By default it will list the files at the root directory.

Here’s an example of how to iterate over the files in the root directory and open them as `File` instances:

```javascript theme={null}
export default defineComponent({
  async run({ steps, $ }) {
    // list all contents of the root File Stores directory in this project
    const dirs = $.files.dir();
    let files = [];
 
    for await(const dir of dirs) {
      // if this is a file, let's open it
      if(dir.isFile()) {
        files.push(await $.files.open(dir.path))
      }
    }
 
    return files
  },
})
```

Each item returned by `$.files.dir()` will contain the following properties:

* `isDirectory()` - `true` if this instance is a directory.
* `isFile()` - `true` if this instance is a file.
* `path` - The path to the file.
* `size` - The size of the file in bytes.
* `modifiedAt` - The last modified at timestamp.

## `File`

This class describes an instance of a single file within a File Store.

When using `$.files.open` or `$.files.openDescriptor`, you’ll create a new instance of a `File` with helper methods that give you more flexibility to perform programmatic actions with the file.

### `File.toUrl()`

*Async.* The pre-signed GET URL to retrieve the file.

```javascript theme={null}
export default defineComponent({
  async run({ steps, $ }) {
    // Retrieve the pre-signed GET URL for logo.png 
    const url = await $.files.open('logo.png').toUrl()
 
    return url
  },
})
 
```

<Note>
  Pre-signed GET URLs are short lived.

  The `File.toUrl()` will expire after 30 minutes.
</Note>

### `File.toFile(path)`

*Async.* Downloads the file to the local path in the current workflow. If the file doesn’t exist, a new one will be created at the path specified.

<Note>
  Only `/tmp` is writable in workflow environments

  Only the `/tmp` directory is writable in your workflow’s execution environment. So you must download your file to the `/tmp` directory.
</Note>

```javascript theme={null}
export default defineComponent({
  async run({ steps, $ }) {
    // Download the file in the File Store to the workflow's /tmp/ directory
    await $.files.open('logo.png').toFile("/tmp/logo.png")
  },
})
 
```

### `File.toBuffer()`

*Async.* Downloads the file as a Buffer to create readable or writeable streams.

```javascript theme={null}
export default defineComponent({
  async run({ steps, $ }) {
    // opens a file at the path "hello.txt" and downloads it as a Buffer
    const buffer = await $.files.open('hello.txt').toBuffer()
    // Logs the contents of the Buffer as a string
    console.log(buffer.toString())
  },
})
```

### `File.fromFile(localFilePath, ?contentType)`

*Async.* Uploads a file from the file at the `/tmp` local path. For example, if `localFilePath` is given `/tmp/recording.mp3`, it will upload that file to the current File Store File instance.

```javascript theme={null}
export default defineComponent({
  async run({ steps, $ }) {
    // Upload a file to the File Store from the local /tmp/ directory
    const file = await $.files.open('recording.mp3').fromFile('/tmp/recording.mp3')
 
    console.log(file.url)
  },
})
```

### `File.fromUrl(url)`

*Async.* Accepts a `url` to read from.

```javascript theme={null}
export default defineComponent({
  async run({ steps, $ }) {
    // Upload a file to the File Store by a URL
    const file = await $.files.open('pipedream.png').fromUrl('https://res.cloudinary.com/pipedreamin/image/upload/t_logo48x48/v1597038956/HzP2Yhq8_400x400_1_sqhs70.jpg')
 
    console.log(file.url)
  },
})
```

### `File.createWriteStream(?contentType, ?contentLength)`

*Async.* Creates a write stream to populate the file with.

<Note>
  Pass the content length if possible

  The `contentLength` argument is optional, however we do recommend passing it. Otherwise the entire file will need to be written to the local `/tmp` before it can be uploaded to the File store.
</Note>

```javascript theme={null}
import { pipeline } from 'stream/promises';
import got from 'got'
 
export default defineComponent({
  async run({ steps, $ }) {
    const writeStream = await $.files.open('logo.png').createWriteStream("image/png", 2153)
 
    const readStream = got.stream('https://pdrm.co/logo')
 
    await pipeline(readStream, writeStream);
  },
})
```

### `File.fromReadableStream(?contentType, ?contentLength)`

*Async.* Populates a file’s contents from the `ReadableStream`.

<Note>
  Pass the content length if possible

  The `contentLength` argument is optional, however we do recommend passing it. Otherwise the entire file will need to be written to the local `/tmp` before it can be uploaded to the File store.
</Note>

```javascript theme={null}
import got from 'got'
 
export default defineComponent({
  async run({ steps, $ }) {
    // Start a new read stream
    const readStream = got.stream('https://pdrm.co/logo')
 
    // Populate the file's content from the read stream
    await $.files.open("logo.png").fromReadableStream(readStream, "image/png", 2153)
  },
})
```

### `File.delete()`

*Async.* Deletes the Project File.

```javascript theme={null}
export default defineComponent({
  async run({ steps, $ }) {
    // Open the Project File and delete it
    const file = await $.files.open('example.png').delete()
 
    console.log('File deleted.')
  },
})
```

<Warning>
  Deleting files is irreversible

  It’s not possible to restore deleted files. Please take care when deleting files.
</Warning>
