跳转至

提供文件和缓存

Aqueduct可以通过返回文件的内容作为HTTP响应体来服务于文件。

FileController

FileController的实例通过HTTP接口从文件系统服务于一个目录。任何引导请求到FileController的路由必须包含一个* 匹配全部。

@override
Controller get entryPoint {
  final router = Router();

  router.route("/files/*").link(() => FileController("public/"));

  return router;
}

FileController的参数是文件系统上的目录,请求路径将被解析到该目录下。在上面的例子中,路径为/files/image.jpg的HTTP请求将返回文件public/image.jpg的内容。

请注意,public/没有前导斜线,因此,目录public必须是相对于Aqueduct应用程序所服务的目录。在实践中,这意味着你可能会有一个像这样的目录结构。

project/
  pubspec.yaml  
  lib/
    channel.dart
    ...
  test/
    ...
  public/
    image.jpg

FileController所服务的目录中添加一个前导斜线将使其相对于文件系统根目录进行解析。

如果请求的路径是一个目录,在搜索要返回的文件时,文件名 index.html将被附加到路径中。

如果一个文件不存在,FileController将返回404 Not Found响应。

文件的Content-Type

FileController将根据送达文件的路径扩展名来设置HTTP响应的内容类型。默认情况下,它可以识别许多常见的扩展类型,如.html.css.jpg.js。你可以给一个实例添加扩展的内容类型:

var controller = FileController("public/")
  ..setContentTypeForExtension("xml", ContentType("application", "xml"));

如果没有用于服务的文件的扩展项,内容类型默认为application/octet-streamFileController永远不会从CodecRegistry中调用任何编码器,但如果存储库允许对文件的内容类型进行压缩,它就会对GZIP数据进行压缩(参见CodecRegistry.addCodecRegistry.setAllowsCompression)。

缓存

FileController总是根据文件系统将响应的Last-Modified头设置为最后修改日期。 如果请求发送If-Modified-Since标头,并且自该日期以来未修改文件,则发送带有适当标头的304 Not Modified响应。

您可以提供Cache-Control标头,具体取决于要提供的文件的路径。 这是一个添加Cache-Control:public,max-age = 31536000的示例

var policy = CachePolicy(expirationFromNow: Duration(days: 365));
var controller = FileController("public/")
  ..addCachePolicy(policy, (path) => path.endsWith(".css"));

FileController之外的文件服务和缓存

任何控制器都可以通过设置Response的主体对象及其内容来为文件提供服务:

var file = File("index.html");

// 首先将内容加载到内存中...
var response = Response.ok(file.readAsStringSync())
  ..contentType = ContentType("application", "html");

// 或通过流传输磁盘中的内容
var response = Response.ok(file.openRead())
  ..encodeBody = false
  ..contentType = ContentType("application", "html");

重要的是要了解Aqueduct如何使用 content-types 处理响应体来服务文件内容。

你可以设置任何ResponseCachePolicy。注意,CachePolicy只修改响应的Cache-Control头。像 Last-Modified 和 ETag 这样的头不被添加。

var response = Response.ok("contents")
  ..cachePolicy = CachePolicy();