LocalFile

***Update Oct. 2021:*** *Observable now supports [**file inputs**](/@observablehq/input-file)! This notebook will remain for history, but please upgrade to [Observable Inputs](/@observablehq/inputs).*

A hack to treat a local file as an Observable FileAttachment, so that you get all the same conveniences (e.g., loading CSV or SQLite). Pass the value option to set the initial value to a file attachment.

const fileView = localFileInput({accept: ".db"})
const file = Generators.input(fileView)
fileView
const db = display(await file.sqlite())
display(await db.describe())
function localFileInput({
  accept, // e.g., ".txt,.md"
  value // set the initial value (typically to a FileAttachment)
} = {}) {
  return Object.assign(htl.html`<form><input type=file ${{accept}} oninput=${(event) => {
    const {currentTarget: input} = event;
    const {form, files: [file]} = input;
    form.value = new LocalFile(file);
  }}>`, {value});
}
class LocalFile extends AbstractFile {
  constructor(file) {
    super(file.name);
    Object.defineProperty(this, "_", {value: file});
    Object.defineProperty(this, "_url", {writable: true});
  }
  async url() {
    return this._url || (this._url = URL.createObjectURL(this._));
  }
  async blob() {
    return this._;
  }
  async stream() {
    return this._.stream();
  }
};
display(LocalFile)
const AbstractFile = FileAttachment("/data/empty@1").constructor.__proto__
display(AbstractFile)