How to read file from an imported library

2019-02-25 03:51发布

问题:

I have two packages: webserver and utils which provides assets to webserver.

The webserver needs access to static files inside utils. So I have this setup:

utils/
  lib/
    static.html

How can I access the static.html file in one of my dart scripts in webserver?

EDIT: What I tried so far, is to use mirrors to get the path of the library, and read it from there. The problem with that approach is, that if utils is included with package:, the url returned by currentMirrorSystem().findLibrary(#utils).uri is a package uri, that can't be transformed to an actual file entity.

回答1:

Use the Resource class, a new class in Dart SDK 1.12.

Usage example:

var resource = new Resource('package:myapp/myfile.txt');
var contents = await resource.loadAsString();
print(contents);

This works on the VM, as of 1.12.

However, this doesn't directly address your need to get to the actual File entity, from a package: URI. Given the Resource class today, you'd have to route the bytes from loadAsString() into the HTTP server's Response object.



回答2:

I tend to use Platform.script or mirrors to find the main package top folder (i.e. where pubspec.yaml is present) and find imported packages exported assets. I agree this is not a perfect solution but it works

import 'dart:io';
import 'package:path/path.dart';

String getProjectTopPath(String resolverPath) {
  String dirPath = normalize(absolute(resolverPath));

  while (true) {
    // Find the project root path
    if (new File(join(dirPath, "pubspec.yaml")).existsSync()) {
      return dirPath;
    }
    String newDirPath = dirname(dirPath);

    if (newDirPath == dirPath) {
      throw new Exception("No project found for path '$resolverPath");
    }
    dirPath = newDirPath;
  }
}

String getPackagesPath(String resolverPath) {
  return join(getProjectTopPath(resolverPath), 'packages');
}

class _TestUtils {}

main(List<String> arguments) {
  // User Platform.script - does not work in unit test
  String currentScriptPath = Platform.script.toFilePath();
  String packagesPath = getPackagesPath(currentScriptPath);
  // Get your file using the package name and its relative path from the lib folder
  String filePath = join(packagesPath, "utils", "static.html");
  print(filePath);

  // use mirror to find this file path
  String thisFilePath =  (reflectClass(_TestUtils).owner as LibraryMirror).uri.toString();
  packagesPath = getPackagesPath(thisFilePath);
  filePath = join(packagesPath, "utils", "static.html");
  print(filePath);
}

To note that since recently Platform.script is not reliable in unit test when using the new test package so you might use the mirror tricks that I propose above and explained here: https://github.com/dart-lang/test/issues/110



标签: dart