--- keywords: file, fileattachment, attachment --- # Files Load files — whether static or generated dynamically by a [data loader](./data-loaders) — using the built-in `FileAttachment` function. This is available by default in Markdown, but you can import it explicitly like so: ```js echo import {FileAttachment} from "observablehq:stdlib"; ``` The `FileAttachment` function takes a path and returns a file handle. This handle exposes: * `name` - the file’s name (such as `volcano.json`), * `mimeType` - [MIME type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types) (such as `application/json`), * `lastModified` - modification time (in milliseconds since epoch), and * `size` - size in bytes . ```js echo FileAttachment("volcano.json") ``` Like a [local import](./imports#local-imports), the path is relative to the calling code’s source file: either the page’s Markdown file or the imported local JavaScript module. To load a remote file, use [`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API), or use a [data loader](./data-loaders) to download the file at build time. Calling `FileAttachment` doesn’t actually load the file; the contents are only loaded when you invoke a [file contents method](#supported-formats). For example, to load a JSON file: ```js echo const volcano = FileAttachment("volcano.json").json(); ``` The value of `volcano` above is a [promise](./reactivity#promises). In other code blocks, the promise is implicitly awaited and hence you can refer to the resolved value directly. ```js echo volcano ``` ## Static analysis The `FileAttachment` function can _only_ be passed a static string literal; constructing a dynamic path such as FileAttachment(\`frame$\{i}.png\`) is invalid syntax. Static analysis is used to invoke [data loaders](./data-loaders) at build time, and ensures that only referenced files are included in the generated output during build. This also allows a content hash in the file name for cache breaking during deploy. If you have multiple files, you can enumerate them explicitly like so: ```js run=false const frames = [ FileAttachment("frame1.png"), FileAttachment("frame2.png"), FileAttachment("frame3.png"), FileAttachment("frame4.png"), FileAttachment("frame5.png"), FileAttachment("frame6.png"), FileAttachment("frame7.png"), FileAttachment("frame8.png"), FileAttachment("frame9.png") ]; ``` None of the files in `frames` above are loaded until a [content method](#supported-formats) is invoked, for example by saying `frames[0].image()`. For missing files, `file.size` and `file.lastModified` are undefined. The `file.mimeType` is determined by checking the file extension against the [`mime-db` media type database](https://github.com/jshttp/mime-db); it defaults to `application/octet-stream`. ## Supported formats `FileAttachment` supports a variety of methods for loading file contents: | method | return type | - | - | [`file.arquero`][arquero] | Arquero [`Table`][arquero-table] | [`file.arrayBuffer`][binary] | [`ArrayBuffer`][array-buffer] | [`file.arrow`][arrow] | Arrow [`Table`][arrow-table] | [`file.blob`][binary] | [`Blob`][blob] | [`file.csv`][csv] | [`Array`][array] | [`file.dsv`][csv] | [`Array`][array] | [`file.html`][markup] | [`Document`][document] | [`file.image`][media] | [`HTMLImageElement`][image] | [`file.json`][json] | [`Array`][array], [`Object`][object], _etc._ | [`file.parquet`][arrow] | Arrow [`Table`][arrow-table] | [`file.sqlite`][sqlite] | [`SQLiteDatabaseClient`][sqlite] | [`file.stream`][binary] | [`ReadableStream`][stream] | [`file.text`][text] | [`string`][string] | [`file.tsv`][csv] | [`Array`][array] | [`file.xlsx`][xlsx] | [`Workbook`][xlsx] | [`file.xml`][markup] | [`Document`][document] | [`file.zip`][zip] | [`ZipArchive`][zip] [arquero]: ./lib/arquero [arquero-table]: https://idl.uw.edu/arquero/api/#table [array-buffer]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer [arrow-table]: https://arrow.apache.org/docs/js/classes/Arrow.dom.Table.html [blob]: https://developer.mozilla.org/en-US/docs/Web/API/Blob [array]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array [document]: https://developer.mozilla.org/en-US/docs/Web/API/Document [image]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement [object]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object [stream]: https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream [string]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String [binary]: #binary-formats [basic]: #basic-formats [arrow]: ./lib/arrow [csv]: ./lib/csv [markup]: #markup [media]: #media [json]: #json [sqlite]: ./lib/sqlite [text]: #text [xlsx]: ./lib/xlsx [zip]: ./lib/zip The contents of a file often dictate the appropriate method — for example, an Excel XLSX file is almost always read with `file.xlsx`. When multiple methods are valid, choose based on your needs. For example, you can load a CSV file using `file.arquero` to load it into [Arquero](./lib/arquero), or even using `file.text` to implement parsing yourself. In addition to the above, you can get the resolved absolute URL of the file using `file.href`: ```js echo FileAttachment("volcano.json").href ``` See [file-based routing](#routing) for additional details. ## Basic formats The following common basic formats are supported natively. ### Text To load a humble text file, use `file.text`: ```js echo const hello = FileAttachment("hello.txt").text(); ``` ```js echo hello ``` By default, `file.text` expects the file to be encoded in [UTF-8](https://en.wikipedia.org/wiki/UTF-8). To use a different encoding, pass the [desired encoding](https://developer.mozilla.org/en-US/docs/Web/API/Encoding_API/Encodings) name to `file.text`. ```js echo const pryvit = FileAttachment("pryvit.txt").text("utf-16be"); ``` ```js echo pryvit ``` ### JSON To load a [JSON (JavaScript Object Notation)](https://www.json.org/) file, use `file.json` ```js echo FileAttachment("volcano.json").json() ``` A common gotcha with JSON is that it has no built-in date type; dates are therefore typically represented as ISO 8601 strings, or as a number of milliseconds or seconds since UNIX epoch. ### Media To display an image, you can use a static image in [Markdown](./markdown) such as `` or `![horse](horse.jpg)`. Likewise, you can use a `video` or `audio` element. Per [file-based routing](#routing), static references to these files are automatically detected and therefore these files will be included in the built output. ```html run=false ``` If you want to manipulate an image in JavaScript, use `file.image`. For example, below we load an image and invert the RGB channel values. ```js echo const canvas = document.querySelector("#horse-canvas"); const context = canvas.getContext("2d"); const horse = await FileAttachment("horse.jpg").image(); context.drawImage(horse, 0, 0, canvas.width, canvas.height); const data = context.getImageData(0, 0, canvas.width, canvas.height); for (let j = 0, k = 0; j < canvas.height; ++j) { for (let i = 0; i < canvas.width; ++i, k += 4) { data.data[k + 0] = 255 - data.data[k + 0]; data.data[k + 1] = 255 - data.data[k + 1]; data.data[k + 2] = 255 - data.data[k + 2]; } } context.putImageData(data, 0, 0); ``` (The images above are from [Eadweard Muybridge](https://www.loc.gov/search/?fa=contributor:muybridge,+eadweard)’s studies of animal locomotion.) ### Markup The `file.xml` method reads an XML file and returns a promise to a [`Document`](https://developer.mozilla.org/en-US/docs/Web/API/Document); it takes a single argument with the file’s MIME-type, which defaults to `"application/xml"`. The `file.html` method similarly reads an [HTML](https://developer.mozilla.org/en-US/docs/Web/HTML) file; it is equivalent to `file.xml("text/html")`. ## Binary formats Load binary data using `file.blob` to get a [`Blob`][blob], or `file.arrayBuffer` to get an [`ArrayBuffer`][array-buffer]. For example, to read [Exif](https://en.wikipedia.org/wiki/Exif) image metadata with [ExifReader](https://github.com/mattiasw/ExifReader): ```js echo import ExifReader from "npm:exifreader"; const buffer = await FileAttachment("horse.jpg").arrayBuffer(); const tags = ExifReader.load(buffer); display(tags); ``` To read a file incrementally, get a [`ReadableStream`][stream] with `file.stream`. For example, to count the number of bytes in a file: ```js echo const stream = await FileAttachment("horse.jpg").stream(); const reader = stream.getReader(); let total = 0; while (true) { const {done, value} = await reader.read(); if (done) break; total += value.length; } display(total); ``` ## Routing Attached files live in the source root (typically `src`) alongside your Markdown pages. For example, say `index.md` has some JavaScript code that references `FileAttachment("quakes.csv")`: ```ini . ├─ src │ ├─ index.md │ └─ quakes.csv └─ … ``` On build, any files referenced by `FileAttachment` will automatically be copied to the `_file` folder under the output root (`dist`), here resulting in: ```ini . ├─ dist │ ├─ _file │ │ └─ quakes.e5f2eb94.csv │ ├─ _observablehq │ │ └─ … # additional assets │ └─ index.html └─ … ``` `FileAttachment` references are automatically rewritten during build; for example, a reference to `quakes.csv` might be replaced with `_file/quakes.e5f2eb94.csv`. (As with imports, file names are given a content hash, here `e5f2eb94`, to improve performance.) Only the files you reference statically are copied to the output root (`dist`), so nothing extra or unused is included in the built site. [Imported local modules](./imports#local-imports) can use `FileAttachment`, too. In this case, the path to the file is _relative to the importing module_ in the same fashion as `import`; this is accomplished by resolving relative paths at runtime with [`import.meta.url`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import.meta). Some additional assets are automatically promoted to file attachments and copied to `_file`. For example, if you have a `` declared statically in a Markdown page, the `style.css` file will be copied to `_file`, too (and the file name given a content hash). The HTML elements eligible for file attachments are `audio`, `img`, `link`, `picture`, and `video`.