** (Response Object) Use in place of a 'File' object to prevent excessive polling of the file system.** As every call to 'File.exists()' typically takes [at least 8ms-12ms]`http://stackoverflow.com/questions/6321180/how-expensive-is-file-exists-in-java#answer-6321277`, ** this is probably a good thing!** ** Generally you would acquire 'FileAssets' from the 'FileHander' and 'PodHander' services and use ** them to embed client URLs in your web pages.** ** fileHandler.fromLocalUrl(`/images/fanny.jpg`).clientUrl** constclass FileAsset {** The file in questionconst File file** Returns 'true' if the file exists. (Or did at the time this class was created.)const Bool exists** Get the modified time of the file, floored to 1 second which is the most precision that HTTP ** can deal with.** ** Returns 'null' if file doesn't existconst DateTime? modified** The ETag uniquely identifies the file and its version. ** The default implementation is a hash of the modified time and the file size.** ** Returns 'null' if file doesn't existconst Str? etag** The size of the file in bytes.** ** Returns 'null' if file doesn't existconst Int? size** The URL relative to the 'BedSheet' [WebMod]`web::WebMod` that corresponds to the file resource. ** If your application is the ROOT WebMod then this will be the same as 'clientUrl'; bar any asset caching. ** If in doubt, use the 'clientUrl' instead.** ** Returns 'null' if file doesn't exist.const Uri? localUrl** The URL that clients (e.g. web browsers) should use to access the file resource. ** The 'clientUrl' contains any extra 'WebMod' path segments required to reach the 'BedSheet WebMod'.** It also contains path segments as provided by any asset caching strategies, such as [Cold Feet]`http://www.fantomfactory.org/pods/afColdFeet`.** ** Client URLs are designed to be used / embedded in your HTML. ** ** Note: use `BedSheetServer` should you want an absolute URL that starts with 'http://'. ** ** Returns 'null' if file doesn't exist.const Uri? clientUrl** Creates a 'FileAsset' for the given file. ** 'localUrl' and 'clientUrl' may be 'null' if this instance is to be passed straight to 'FileResponseProcessor'. @NoDocnew make(File file, Uri? localUrl := null, Uri? clientUrl := null, |This|? in := null){this.file = filethis.exists = file.existsthis.modified = file.modified?.floor(1sec)this.size = file.sizethis.etag = this.exists ? "${this.size?.toHex}-${this.modified?.ticks?.toHex}" : nullthis.localUrl = localUrlthis.clientUrl = clientUrl in?.call(this)} @NoDocoverride Int hash(){ file.hash} @NoDocoverride Bool equals(Obj? obj){ file == (obj as FileAsset)?.file}** Returns 'clientUrl' so this can be printed in HTML, or 'file.toStr' if 'clientUrl' is 'null'.override Str toStr(){ clientUrl?.toStr ?: file.toStr}}