---
title: Fliplet.Media
description: "Browse folders, upload and manage files, and download media to devices via the Fliplet Media namespace."
type: api-reference
tags: [js-api, media]
v3_relevant: false
deprecated: false
exclude_from_v3_catalog: true
---
# `Fliplet.Media`

Browse folders, upload and manage files, and download media to devices via the Fliplet Media namespace. Capturing or uploading a photo in a V3 app? See the [V3 media guide](./v3/media.md).

---

## Folders

### Get the list of folders and files for your organization or a specific app

```js
// By default, this gets all top-level folders and files for the current app
Fliplet.Media.Folders.get().then(function (response) {
  // response.folders
  // response.files
});

// Get a list of all top-level folders and files for an organization by its ID
Fliplet.Media.Folders.get({ organizationId: 1 }).then(function (response) {});

// Get a list of all top-level folders and files for an app by its ID
Fliplet.Media.Folders.get({ appId: 2 }).then(function (response) {});

// Get a list of files and subfolders for a specific folder by its ID
Fliplet.Media.Folders.get({ folderId: 3 }).then(function (response) {});
```

Sample response for the above methods:

```json
{
  "files": [
    {
      "appId": null,
      "contentType": "image/jpeg",
      "createdAt": "2019-01-07T16:58:43.609Z",
      "id": 1,
      "isEncrypted": true,
      "mediaFolderId": null,
      "name": "Foo.jpg",
      "organizationId": 123,
      "path": "apps/1/2895a2611b753a74f2ae5097411579e4223-234-2632.jpg",
      "size": [ 640, 480 ],
      "metadata": {
        "size": 10438,
        "checksum": "29b5d83988d3d4c28af2109418674e20"
      },
      "thumbnail": "https://path/to/thumbnail.jpg",
      "updatedAt": "2019-01-07T16:58:43.619Z",
      "url": "https://path/to/secure-file.jpg",
      "userId": 1
    },
  ],
  "folders": [
    {
      "appId": null,
      "createdAt": "2019-01-08T17:06:03.377Z",
      "deletedAt": null,
      "id": 1,
      "name": "My folder",
      "organizationId": 2,
      "parentId": null,
      "updatedAt": "2019-01-08T17:06:03.377Z"
    }
  ]
}
```

Notes:

- `parentId` on a folder indicates whether this folder is a subfolder of another folder. If you want to query for all subfolders of a folder, provide the `folderId` parameter to the above JS APIs with the required ID.
- `size` is an array with the width and height for images.
- `metadata` is an object containing the file size in bytes and its md5 checksum.

### Create a new folder

```js
// Create a folder belonging to the current app
Fliplet.Media.Folders.create({ name: 'foo' }).then(function (folder) { });
```

### Delete a folder

```js
// Delete a folder given its id
Fliplet.Media.Folders.delete(1).then(function onComplete() { });
```

### Rename a folder

```js
Fliplet.Media.Folders.update(123, {
  name: 'Foo'
});
```

### Move a folder

```js
Fliplet.Media.Folders.update(123, {
  appId: 123,         // move to an app
  parentId: 456,      // move to a folder
  organizationId: 789 // move to the organization
});
```

Note: when moving a folder out from a subfolder (and to an app or organization), please set its `parentId` to `null`.

## Files

### Upload one or more files

Files can be added using the standard HTML APIs for [FormData](https://developer.mozilla.org/en/docs/Web/API/FormData).

<p class="quote"><strong>Note:</strong> Fliplet scans all uploaded files for viruses. If a file is found to be infected the system will automatically quarantine it and not allow apps to download it. Quarantined files can be seen in the trash folder of the File Manager in Fliplet Studio.</p>

```js
Fliplet.Media.Files.upload({
  data: FormData,
  folderId: 1 // optional folderId
}).then(function (files) {

});
```

Please note that the following image content types are automatically resized to have both dimensions no larger than `3840px`; when a resizing occurs, the scale of the image will be kept intact:

- `image/apng`: Animated Portable Network Graphics (APNG)
- `image/avif`: AV1 Image File Format (AVIF)
- `image/jpeg`: Joint Photographic Expert Group image (JPEG / JPG)
- `image/png`: Portable Network Graphics (PNG)
- `image/svg+xml`: Scalable Vector Graphics (SVG)
- `image/webp`: Web Picture format (WEBP)

### Delete a file

```js
// Delete a file given its id
Fliplet.Media.Files.delete(2).then(function onComplete() { });
```

### Rename a file

```js
Fliplet.Media.Files.update(123, {
  name: 'Foo'
});
```

### Move a file

```js
Fliplet.Media.Files.update(123, {
  appId: 123,         // move to an app
  mediaFolderId: 456, // move to a folder
  organizationId: 789 // move to the organization
});
```

Note: when moving a file from a folder to an app or organization, please set its `mediaFolderId` to `null`.

### Get file metadata

Fetches the metadata object for a single file by its ID.

```js
Fliplet.Media.Files.get(123).then(function (file) {
  console.log(file.name, file.url, file.contentType);
});
```

Endpoint: `GET v1/media/files/{id}`

The resolved object has the same shape as the entries returned by `Fliplet.Media.Folders.get()` — see the [sample response](#get-the-list-of-folders-and-files-for-your-organization-or-a-specific-app) above for the full field list.

### Get metadata for multiple files

Fetches metadata for a list of files in a single request. On native platforms the result is cached in `Fliplet.Cache` for 1 hour (keyed by a hash of the request body), so repeated calls with the same arguments avoid redundant network traffic.

```js
Fliplet.Media.Files.getAll({
  files: [123, 456, 789],
  attributes: ['id', 'name', 'url', 'updatedAt'] // optional — omit to get all fields
}).then(function (files) {
  files.forEach(function (file) {
    console.log(file.id, file.name);
  });
});
```

Endpoint: `POST v1/media/files/aggregate`

The `files` array contains the numeric IDs of the files to fetch. The optional `attributes` array limits which fields the server returns.

### Get file contents

Fetches the raw contents of a file. Pass optional transform parameters to have the server resize or convert images before delivery.

```js
// Fetch an image resized to the "medium" preset (960 px on the longest side)
// and converted to WebP at 80% quality
Fliplet.Media.Files.getContents(123, {
  size: 'medium', // small | medium | large | xlarge | xxlarge | xxxlarge
  format: 'webp', // jpg | webp
  quality: 80     // 1–100; defaults to 88 for jpg and 80 for webp
}).then(function (contents) {
  // contents type depends on the server response and any responseType override
});
```

Endpoint: `GET v1/media/files/{id}/contents`

**Transform options:**

| Option | Type | Description |
|---|---|---|
| `size` | String | Named size preset (`small` 640 px, `medium` 960 px, `large` 1366 px, `xlarge` 1980 px, `xxlarge` 2560 px, `xxxlarge` 3840 px) or a raw ImageMagick geometry string. The server scales proportionally and skips resizing when the image is already within the requested dimension. |
| `format` | String | Output image format. Accepted values: `jpg`, `webp`. |
| `quality` | Number | Compression quality from 1 to 100. Defaults to `88` for `jpg` and `80` for `webp` when `format` is set. |

### Get cached images

Matches a local list of file names against a server folder, downloads any files that are missing or stale, and returns resolved metadata for each matched file. On web, no file is downloaded — signed content URLs are returned directly. On native platforms, files are stored to device storage via `Fliplet.Native.Downloads.downloadFile` and per-file metadata is tracked with `Fliplet.Storage` so that subsequent calls skip files that have not changed on the server.

```js
Fliplet.Media.Files.getCachedImages({
  folderId: 456,                // ID of the Media folder to sync from
  files: [                      // local list of files to match
    { name: 'hero.jpg' },
    { name: 'logo.png' }
  ],
  size: 'large',                // optional transform options (same as getContents)
  format: 'webp',
  quality: 80,
  onProgress: function (file, fileInfo) {
    // called after each file is resolved or downloaded
    console.log('Ready:', file.name, fileInfo.path);
  }
}).then(function (images) {
  // images is an array of objects:
  // { id, path, fileName, name, updatedAt }
  images.forEach(function (img) {
    document.querySelector('#' + img.name).src = img.path;
  });
});
```

Each entry in the resolved array contains:

| Property | Description |
|---|---|
| `id` | Numeric ID of the file on the server. |
| `path` | On web: authenticated content URL. On native: absolute local file path. |
| `fileName` | Local file name used for storage (includes folder ID and transform tokens). |
| `name` | Original file name as matched against the `files` input list. |
| `updatedAt` | Timestamp of the file version that was last downloaded. |

Files present in the `files` input list but not found in the server folder are silently omitted from the result.

---

## Search folders and files

Use the `search()` method fo find folders and files in your app or organization or a specific folder.

- You can search by `name`
- You can filter results by `appId`, `organizationId` or `folderId`
- You can search for deleted files and folders by specifying `deletedOnly` as `true`
- Results will include a `type` (`folder` or `file`)
- Results will include `app` and `organization` properties with `{ id, name }` when available
- Results will include a `parentFolder` with `{ id, name }` which recursively include any folder up to their app or organization folder

```js
// search by file name
Fliplet.Media.Folders.search({ name: 'foo' })

// search by app
Fliplet.Media.Folders.search({ appId: 123 })

// search by organization
Fliplet.Media.Folders.search({ organizationId: 456 })

// search by folder
Fliplet.Media.Folders.search({ folderId: 789 })

// search for deleted files and folders only
Fliplet.Media.Folders.search({ deletedOnly: true })
```

Sample response:

```json
[
  {
    "appId": null,
    "contentType": "image/jpeg",
    "createdAt": "2019-06-07T14:39:04.194Z",
    "dataSourceEntryId": null,
    "dataTrackingId": null,
    "deletedAt": null,
    "id": 267,
    "isEncrypted": true,
    "isOrganizationMedia": false,
    "masterMediaFileId": null,
    "mediaFolderId": 54,
    "name": "Foo bar.jpg",
    "organization": {
      "id": 11,
      "name": "Otro company"
    },
    "organizationId": 11,
    "parentFolder": {
      "app": {
        "id": 147,
        "name": "Hello world"
      },
      "id": 54,
      "name": "Subfolder in app",
      "parentFolder": {
        "app": {
          "id": 147,
          "name": "Hello world"
        },
        "id": 53,
        "name": "Folder in app"
      }
    },
    "size": [ 4400, 2750 ],
    "thumbnail": "https://path/to/thumbnail/54/05bbf86878931661858c42441db0c2ce614-439-6054-t.jpg",
    "type": "file",
    "updatedAt": "2019-06-07T14:39:04.202Z",
    "url": "https://api.fliplet.com/v1/media/files/123/contents/hello-world.jpg",
    "userId": 245
  }
]
```

---

## Authentication

### Authenticate encrypted files

Media files might require an auth token to be accessed if your organization has encryption enabled. We have a little helper available to do the heavy lifting for you, just pass any media file url or even a string with many URLs in it and they'll get patched automatically:

```js
// Authenticate a URL by passing the mediaFile URL
var authenticatedUrl = Fliplet.Media.authenticate(mediaFile.url);

// Authenticate all URLs found in a String
var authenticatedHtml = Fliplet.Media.authenticate('<img src="https://api.fliplet.com/v1/media/files/123/contents/Foo.jpg" />');
```

If you're using Handlebars to print out your URLs, you can use our built-in `auth` helper:

{% raw %}
```handlebars
<img src="{{{auth someFileUrl}}}" />
```
{% endraw %}

You can also create your own helper if you need more control:

```js
Handlebars.registerHelper('addAuthentication', function(str) {
  return new Handlebars.SafeString(Fliplet.Media.authenticate(str));
});
```

And then use it in your directory templates like:

{% raw %}
```handlebars
<img src="{{{addAuthentication someFileUrl}}}" />

<p>The authenticated URL is {{{addAuthentication someContent}}}</p>
```
{% endraw %}

---

## Download files to devices

As per most or Fliplet JS APIs, all the following methods **return a promise**. There is experimental support on Chrome (for webapps) and full support is only available on native platforms (iOS and Android).

### Get the list of files downloaded on the device, including files being downloaded

```js
// Get an array of downloaded filed and files pending to be downloaded
Fliplet.Media.Files.Storage.get().then(function (files) {
  // Each file has status (downloaded or downloading), size, downloadedAt,
  // name and url (the original http(s) url used to download the file)
});

// Get downloaded files only
Fliplet.Media.Files.Storage.getDownloaded();

// Search for a downloaded file by url. "file" is undefined when not found
Fliplet.Media.Files.Storage.getDownloaded(url).then(function (file) {});

// Search for downloaded files by providing a filter identity sent to lodash "filter"
Fliplet.Media.Files.Storage.getDownloaded({ size: 100 }).then(function (files) {});

// Get downloading (pending) files only
Fliplet.Media.Files.Storage.getDownloading();
```

---

### Download a file

```js
// Downloads a file (this gets added to a queue and will be downloaded in background)
Fliplet.Media.Files.Storage.download(remoteUrl);

// You can also add to the download queue an array of files
Fliplet.Media.Files.Storage.download([url1, url2, url3]);
```

---

### Resume pending operations

```js
// Call this in your screen JS after registering hooks
Fliplet.Media.Files.Storage.ready();
```

---

### Return most appropriate URL to a file

```js
Fliplet.Media.Files.Storage.resolve(url).then(function (fileUrl) {
  // fileUrl can be used to play an audio, display an image, etc
});
```


---

### Get the raw FileEntry for a local file

```js
// requires the fileName from any "file.name"
Fliplet.Media.Files.Storage.getFile(fileName).then(function (file) {

});
```

---

### Deletes one or more files

```js
// Deletes a file. Requires the "file.name" or "file.url"
Fliplet.Media.Files.Storage.delete(fileName)

// Deletes an array of files
Fliplet.Media.Files.Storage.delete([fileName1, fileName2, fileURL3])

// Deletes all files
Fliplet.Media.Files.Storage.deleteAll()
```

### Cancels one or more pending downloads

```js
// Cancels the download a file. Requires the file URL
Fliplet.Media.Files.Storage.cancelDownload(fileURL)

// Cancels the download of more files at once
Fliplet.Media.Files.Storage.cancelDownload([fileURL1, fileURL2, fileURL3])
```

### Hooks

```js
Fliplet.Hooks.on('mediaFileDownloadCompleted', function (file) {

  // Resolve URL
  Fliplet.Media.Files.Storage.resolve(file).then(function (url) {
    // Add audio player
    $('body').append('<div data-title="Offline file" data-audio-url="' + url + '"></div>');

    // Init player so file can be played
    Fliplet.Media.Audio.Player.init()
  });
});

Fliplet.Hooks.on('mediaFileDownloadFailed', function (error) {
 console.error('error downloading file', this, 'with error', error);
});

Fliplet.Hooks.on('mediaFileDownloadCanceled', function (fileData) {
 console.error('canceled a download', fileData);
});

Fliplet.Hooks.on('mediaFileDownloadProgress', function (file) {
 console.debug('progress', file.progress.loaded, 'of', file.progress.total);
});
```

---

[Back to JS API documentation](../API-Documentation)
{: .buttons}
