# Send files and streams to the client

> Serve a file from disk with $.file(), force a download name, stream generated content with $.stream() and answer with 404 when the file is missing.

Framework: total5
Product: Total.js 5 (total5@0.0.19)
Language: en
Content-SHA256: c21ebfd97c7af12b738ceba0374203c527f79fc70b1373c215c4a4462f8009d4
Snapshot: c0700e321579725c5cf4f5ace1ad7d2866d1b4f93c24a63c0b41b6b7998e976c
Sources: total5-installed@total5@0.0.19
Review: not-recorded

`$.file(path, [download])` sends a file from disk. The `content-type` comes from the extension. Pass `true` as the second argument to make the browser download the file under its own name, or a string to choose the name (`attachment; filename*=...` is set for you, UTF-8 safe). A path that does not exist ends with the 404 page.

`$.stream(type, stream, [download])` sends any readable stream with the given content type: a generated file, a response from another server or a database export. It sets no length, so the response is chunked. `PATH.public()`, `PATH.private()` and `PATH.tmp()` build absolute paths into the project folders; files in `public/` are already served without any route, so use `$.file()` for the files that must stay private or need a check first.

```js controllers/download.js
const Fs = require('fs');

exports.install = function() {
	ROUTE('GET /report/', report);
	ROUTE('GET /report/save/', report_save);
	ROUTE('GET /export/', export_csv);
	ROUTE('GET /missing/', missing);
};

function filepath() {
	var filename = PATH.tmp('report.txt');
	Fs.writeFileSync(filename, 'Total.js report\n');
	return filename;
}

function report($) {
	$.file(filepath());
}

function report_save($) {
	$.file(filepath(), 'my report.txt');
}

function export_csv($) {
	var stream = Fs.createReadStream(filepath());
	$.stream('text/csv', stream, 'export.csv');
}

function missing($) {
	$.file(PATH.tmp('does-not-exist.txt'));
}
```
