Files

The files plugin is blob storage for Kibana plugins: create file metadata, upload content, and download through scoped HTTP APIs.

The default blob store is Elasticsearch. The service optimizes how ES is used for blobs, but ES is not a blob store by design. Report performance problems if you see them.

Note

The service does not encrypt contents at rest and does not compress blobs. Files live in a system index. Plugins can still expose contents over HTTP, so only enable the actions you need and do not store secrets in files.

A file is Saved Object metadata plus a separate blob. Create the metadata first (the upload target), then upload content.

File contents are immutable. After upload, clients should download once and cache. To change contents, create a new file.

Consumers can attach JSON-serializable custom metadata and search it for tagging and filtering.

Examples below follow examples/files_example.

Add files to requiredPlugins in kibana.jsonc.

A file kind is one use case (for example user avatars). Register the full kind on the server — that is where HTTP privilege tags and size limits are enforced. Register a browser subset (id, allowedMimeTypes, and maxSizeBytes) on the client.

If the server omits maxSizeBytes, it enforces a 4 MiB limit. The upload UI only checks size when the browser registration includes maxSizeBytes; it does not apply that server default itself.

import type { FileKind } from '@kbn/files-plugin/common';

export const PLUGIN_ID = 'filesExample';

const httpTags = {
  requiredPrivileges: [PLUGIN_ID],
};

export const exampleFileKind: FileKind = {
  id: PLUGIN_ID,
  maxSizeBytes: 8 * 1024 * 1024,
  allowedMimeTypes: ['image/png', 'image/jpeg'],
  http: {
    create: httpTags,
    delete: httpTags,
    download: httpTags,
    getById: httpTags,
    list: httpTags,
  },
};
		

Only list the HTTP actions you need. httpTags.requiredPrivileges are the API authorization privileges on the generated file-kind routes. Grant those privileges to the users who must reach the files.

// server
public setup(core: CoreSetup, { files }: { files: FilesSetup }) {
  files.registerFileKind(exampleFileKind);
}

// browser — FileKindBrowser only
public setup(core: CoreSetup, { files }: { files: FilesSetup }) {
  files.registerFileKind({
    id: exampleFileKind.id,
    allowedMimeTypes: exampleFileKind.allowedMimeTypes,
    maxSizeBytes: exampleFileKind.maxSizeBytes,
  });
}
		

Browser start uses filesClientFactory. The HTTP client is scoped to one kind. Pass a contentType from allowedMimeTypes on upload — the client defaults to application/octet-stream, which the server rejects when that type is not allowed:

const client = files.filesClientFactory.asScoped('filesExample');
const result = await client.list();

const { file } = await client.create({
  name: 'my_file',
  meta: { myValue: 'test' },
  mimeType: 'image/png',
});

await client.upload({
  id: file.id,
  body: blob,
  contentType: 'image/png',
});
		

Server start uses fileServiceFactory. asInternal() does not go through HTTP ACLs and has unrestricted access to that kind:

const fileService = files.fileServiceFactory.asInternal();
const file = await fileService.create({
  fileKind: 'filesExample',
  name: 'my_file',
  meta: { myValue: 'test' },
  mime: 'image/png',
});

await file.uploadContent(readable);
		

Shared file UI lives in @kbn/shared-ux-file-* packages. Wrap the tree in FilesContext with an unscoped client:

import { FilesContext } from '@kbn/shared-ux-file-context';
import { FilePicker } from '@kbn/shared-ux-file-picker';
import { FileUpload } from '@kbn/shared-ux-file-upload';
import { FileImage as Image } from '@kbn/shared-ux-file-image';

const client = files.filesClientFactory.asUnscoped();

<FilesContext client={client}>
  <FilePicker kind="filesExample" onDone={onDone} onClose={onClose} />
  <FileUpload kind="filesExample" onDone={onDone} />
  <Image src={client.getDownloadHref({ id, fileKind: 'filesExample' })} alt="..." />
</FilesContext>
		

See examples/files_example and the public contracts in public/index.ts and server/index.ts.