# Enviar ficheiros e streams ao cliente

> Sirva um ficheiro do disco com $.file(), force um nome de descarga, envie conteúdo gerado com $.stream() e responda 404 quando o ficheiro não existe.

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

`$.file(path, [download])` envia um ficheiro do disco. O `content-type` vem da extensão. Passe `true` como segundo argumento para que o navegador descarregue o ficheiro com o seu próprio nome, ou uma string para escolher o nome (`attachment; filename*=...` é definido por si, seguro com UTF-8). Um caminho que não existe termina com a página 404.

`$.stream(type, stream, [download])` envia qualquer stream legível com o content type indicado: um ficheiro gerado, a resposta de outro servidor ou uma exportação de base de dados. Não define o comprimento, por isso a resposta vai em chunks. `PATH.public()`, `PATH.private()` e `PATH.tmp()` constroem caminhos absolutos para as pastas do projeto; os ficheiros de `public/` já são servidos sem qualquer rota, por isso use `$.file()` para os ficheiros que devem continuar privados ou que precisam de uma verificação prévia.

```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'));
}
```
