How do I get the Asset's file path in flutter?
Asked Answered
C

5

34

Here is my pubspec.yaml:

  assets:
    - assets/mySecertImage.png

Here is how I read back the assets:

  var data = await PlatformAssetBundle().load('assets/mySecertImage.png');

Instead of reading it directly, can I get the file path instead? If it is not possible to do so, it is possible to change the data to become a File object? Thanks.

Cableway answered 16/9, 2018 at 11:43 Comment(2)
Would it solve your problem reading from the bundle and saving it to a real file when starting the app (in the main method)? If so let me know and I'll show you the code to do just that.Endymion
This code will work perfectly Future<File> getImageFileFromAssets(String path) async { final byteData = await rootBundle.load('assets/$path'); final buffer = byteData.buffer; Directory tempDir = await getTemporaryDirectory(); String tempPath = tempDir.path; var filePath = tempPath + '/file_01.tmp'; // file_01.tmp is dump file, can be anything return File(filePath) .writeAsBytes(buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes)); }Flaunt
I
28

Have you found a solution ? (I am looking for the same as well).

Here is a workaround that I pursue (out of lack of a better idea)... :

I do:

  • create a new File-path to your Documents-directory (named app.txt in the below code-example)
  • copy the File sitting in your assets folder to this Documents-directory location
  • work with the copied file from now on (where you now have File-path and even Byte-content if needed)

Here is the Dart-code:

import 'package:path/path.dart';

Directory directory = await getApplicationDocumentsDirectory();
var dbPath = join(directory.path, "app.txt");
ByteData data = await rootBundle.load("assets/demo.txt");
List<int> bytes = data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
await File(dbPath).writeAsBytes(bytes);

Some people also work with the getDatabasesPath() instead of getApplicationDocumentsDirectory(). But I figured that on an iOS-Simulator this ends up being the exact same location. (not verified on Android)... So, it would say:

var dbDir = await getDatabasesPath();
var dbPath = join(dbDir, "app.txt");
ByteData data = await rootBundle.load("assets/demo.txt");
List<int> bytes = data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
await File(dbPath).writeAsBytes(bytes);

For an iOS-Simulator: In both above examples, you can find your copied file under the folder:

/Users/username/Library/Developer/CoreSimulator/Devices/AE5C3275-CD65-3537-9B32-53533B97477C/data/Containers/Data/Application/7BE2B2EE-4E45-3783-B4BD-341DA83C43BD/Documents/app.txt

(of course, the UUID's being different in your case...)

And if you want to copy the file only if it does not exist already, you could write:

Directory directory = await getApplicationDocumentsDirectory();
var dbPath = join(directory.path, "app.txt");
if (FileSystemEntity.typeSync(dbPath) == FileSystemEntityType.notFound) {
  ByteData data = await rootBundle.load("assets/demo.txt");
  List<int> bytes = data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
  await File(dbPath).writeAsBytes(bytes);
}
Intelligibility answered 17/12, 2018 at 14:41 Comment(4)
What is 'rootBundle' then?Lurette
@OliverDixon rootBundle is a Flutter library. import 'package:flutter/services.dart' show rootBundle; See here for more info : flutter.dev/docs/development/ui/assets-and-imagesSummersault
please don't forget to add first the dependency path_provider: ^1.3.0 to pubspec.yaml other the getApplicationDocumentsDirectory() will give you error.Encircle
@Encircle How do I express my gratitude for just mentioning that! I saw various articles about this,,but none, not even a google sample for FireStore mentioned that "Do not forget to add depdendency for this". Coming from Native Android I was in an illusion it should be OOB, took me 30mins to figure this out! Thank you!Singapore
C
11

You can not get the file path of an asset file, because assets, that are bundled with your app, are stored inside an archive.

See the "Asset building" section here:

https://flutter.dev/docs/development/ui/assets-and-images#asset-bundling

During a build, Flutter places assets into a special archive called the asset bundle that apps read from at runtime.

Cover answered 21/9, 2020 at 15:4 Comment(0)
F
6

I had the same issue but fixed by calling this.

Future<File> getImageFileFromAssets(String path) async {
 final byteData = await rootBundle.load('assets/$path');
 final buffer = byteData.buffer;
 Directory tempDir = await getTemporaryDirectory();
 String tempPath = tempDir.path;
 var filePath =
  tempPath + '/file_01.tmp'; // file_01.tmp is dump file, can be anything
 return File(filePath)
  .writeAsBytes(buffer.asUint8List(byteData.offsetInBytes, 
 byteData.lengthInBytes));
}
Flaunt answered 19/2, 2022 at 16:6 Comment(0)
H
4

An alternative to Harjinder's implementation: It handles the case that the path includes directories and it avoids rewriting the file

  Future<File> _getImageFileFromAssets(String path) async {
    Directory tempDir = await getTemporaryDirectory();
    String tempPath = tempDir.path;
    var filePath = "$tempPath/$path";
    var file = File(filePath);
    if (file.existsSync()) {
      return file;
    } else {
      final byteData = await rootBundle.load('assets/$path');
      final buffer = byteData.buffer;
      await file.create(recursive: true);
      return file
          .writeAsBytes(buffer.asUint8List(byteData.offsetInBytes,
          byteData.lengthInBytes));
    }
  }
Hickerson answered 20/10, 2022 at 4:17 Comment(0)
O
0

Also make sure sometimes is required to specify the path as following: 'packages/$nameOfThePackage/$assetPath' if your assets are in a separate package you might use for splitting the features. nameOfThePackage being the library name of the alternative package you use. assetPath as an example is 'assets/images/'

Orthodontia answered 14/9, 2023 at 10:38 Comment(1)
As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.Aleishaalejandra

© 2022 - 2024 — McMap. All rights reserved.