diff --git a/packages/flutter_tools/lib/src/build_runner/devfs_web.dart b/packages/flutter_tools/lib/src/build_runner/devfs_web.dart index 7a3630774c..b25204ecf0 100644 --- a/packages/flutter_tools/lib/src/build_runner/devfs_web.dart +++ b/packages/flutter_tools/lib/src/build_runner/devfs_web.dart @@ -157,11 +157,9 @@ class WebAssetServer implements AssetReader { // If all of the lookups above failed, the file might have been an asset. // Try and resolve the path relative to the built asset directory. if (!file.existsSync()) { - final String assetPath = requestPath.replaceFirst('/assets/', ''); - file = globals.fs.file( - globals.fs.path.join(getAssetBuildDirectory(), - globals.fs.path.relative(assetPath)), - ); + final Uri potential = globals.fs.directory(getAssetBuildDirectory()) + .uri.resolve( requestPath.replaceFirst('/assets/', '')); + file = globals.fs.file(potential); } if (!file.existsSync()) { diff --git a/packages/flutter_tools/test/general.shard/web/devfs_web_test.dart b/packages/flutter_tools/test/general.shard/web/devfs_web_test.dart index 2883017cde..0a26ce7d2f 100644 --- a/packages/flutter_tools/test/general.shard/web/devfs_web_test.dart +++ b/packages/flutter_tools/test/general.shard/web/devfs_web_test.dart @@ -150,6 +150,20 @@ void main() { Platform: () => windows, })); + test('serves asset files from in filesystem with url-encoded paths', () => testbed.run(() async { + final File source = globals.fs.file(globals.fs.path.join('build', 'flutter_assets', Uri.encodeFull('abcd象形字.png'))) + ..createSync(recursive: true) + ..writeAsBytesSync(kTransparentImage); + final Response response = await webAssetServer + .handleRequest(Request('GET', Uri.parse('http://foobar/assets/abcd%25E8%25B1%25A1%25E5%25BD%25A2%25E5%25AD%2597.png'))); + + expect(response.headers, allOf([ + containsPair('content-length', source.lengthSync().toString()), + containsPair('content-type', 'image/png'), + ])); + expect((await response.read().toList()).first, source.readAsBytesSync()); + })); + test('serves asset files from in filesystem with known mime type on Windows', () => testbed.run(() async { final File source = globals.fs.file(globals.fs.path.join('build', 'flutter_assets', 'foo.png')) ..createSync(recursive: true)