# Files (addressing something the app stores)

> The platform stores a file two ways, and which one you hold decides how you address it. A PATH-keyed file lives at an address you chose and becomes a URL with `File.Url` (public) or `File.SignedUrl` (a time-limited grant to one caller). A `FileAsset` is a ROW with its own security and NO path at all — neither of those verbs can address one; you put it on a page with `Image(fileAsset: row.Photo.Id)` and the platform works the address out.

<!-- id: storage-index · area: storage · stability: stable · html: https://osysharp.com/reference/storage/index/ -->

## Summary        {#summary}
**There are two stores, and the first thing to know is which one you are holding.**

| what you have | how it is addressed | shown with |
|---|---|---|
| a **path** — `"public/logo.png"`, an [upload](https://osysharp.com/reference/ui/upload/) result | `File.Url(path)` · `File.SignedUrl(path)` | `Image(src: File.Url(path))` |
| a **`FileAsset`** — a row, from `File.Create` or `Image.Thumbnail`, or a `FileAsset` field | it has **no path**; the platform addresses it | `Image(fileAsset: row.Photo.Id)` — see [Showing a picture on a page](https://osysharp.com/reference/ui/image/) |

⚠ The verbs on this page take a **path string**. A `FileAsset` carries none, so `File.Url(asset)` and
`File.SignedUrl(asset)` do not exist and the compiler refuses them — that is the commonest first-day mistake, and
[Showing a picture on a page](https://osysharp.com/reference/ui/image/) is what you wanted.

**Within the path store, a stored file is addressed by URL, and which URL you ask for is an access decision.**

```osy title="public, and not public" test app=storage-index
using Osysharp.Storage;

[Principal] entity User { [MaxLength(200)] string Email; }

entity Item { [Required, MaxLength(200)] string ImagePath; }

// Anyone may fetch this — it is an asset, served to whoever asks.
string PublicImage(Item item) { return File.Url(item.ImagePath); }

// This one belongs to somebody, so the URL carries its own expiring grant.
string PrivateReport(User user) { return File.SignedUrl("reports/" + user.Id + "/q3.pdf"); }
```

## Description    {#description}
**[File.Url](https://osysharp.com/reference/storage/file-url/) is pure sugar over the serving route** — an app-relative path becomes `/_osy/files/…`, which
means it works directly inside a render argument. It grants nothing: what it addresses is served to whoever asks,
so it is right for assets and wrong for anything a person owns.

**[File.SignedUrl](https://osysharp.com/reference/storage/file-signed-url/) is the other case**, and it is the one to reach for by default when the file belongs
to somebody: the URL carries its own time-limited grant, so sharing it is a decision with an expiry rather than a
permanent one.

## See also   {#see-also}
- [Showing a picture on a page](https://osysharp.com/reference/ui/image/) — putting a picture on a page, from either store
- [File.Url](https://osysharp.com/reference/storage/file-url/) — the public address of a PATH, and where it is safe
- [File.SignedUrl](https://osysharp.com/reference/storage/file-signed-url/) — a time-limited grant to one caller, over a PATH
- [Image.Thumbnail, Resize and Convert (a stored image, transformed)](https://osysharp.com/reference/storage/images/) — a stored image transformed: `Image.Thumbnail`, `Resize`, `Convert`, each a new `FileAsset`
