I am building an application with Flutter. I am using using a mix of newer technologies that I am struggling to piece together.
My actual issue is that I cannot get images to load in the app when using the following methods:
- Insert test data into MongoDB using Mongoengine, images are inserted into GridFS using this method.
- Query GraphQL server for data and retrieve data and receive images from GridFS in form of
bytes
but in astring
- e.g "b'/9j/4AAQSkZJRgABAQEASABIAAD/4V0X .... '" - Use that bytes string to load images in app with something like Image.memory()
But the images fail to load with an error: type String is not a subtype of type Uint8List
. So I tried to convert the string of bytes from a String to raw bytes by doing:
List<int> bytesList = imageData['image']['data'].codeUnits;
Uint8List thumbImageBytes = Uint8List.fromList(bytesList);
I get the following exception:
I/flutter ( 4303): ══╡ EXCEPTION CAUGHT BY IMAGE RESOURCE SERVICE ╞══════
I/flutter ( 4303): The following _Exception was thrown while resolving an image:
I/flutter ( 4303): Exception: Could not instantiate image codec.
I have no idea what I can do to fix this, I cannot seem to find anything by googling etc. It would seem there is no information available for this exact scenario except for this S.O question which is what I have tried to do. I have also tried all the methods sugested in comments, followed the suggested links and tried all available combinations of answers, comments, everything.
My set up is as follows;
Main app: Flutter/Dart
API Server: Python/Flask/Mongoengine based GraphQL/Graphene API
Backend Database: MongoDB
The Python side;
A Mongoengine Document model:
class Product(Document):
meta = {'collection': 'product'}
name = StringField(unique=True)
price = FloatField()
sale_price = FloatField()
description = StringField()
image = FileField()
thumb = FileField()
created_at = DateTimeField(default=datetime.utcnow)
edited_at = DateTimeField()
# user = ReferenceField(User)
def __repr__(self):
return f'<Product Model::name: {self.name}>'
A Graphene schema for the model:
class ProductAttribute:
name = graphene.String()
price = graphene.Float()
sale_price = graphene.Float()
description = graphene.String()
image = Upload()
thumb = graphene.String()
created_at = graphene.DateTime()
edited_at = graphene.DateTime()
class Product(MongoengineObjectType):
"""Product node."""
class Meta:
model = ProductModel
interfaces = (graphene.relay.Node,)
class CreateProductInput(graphene.InputObjectType, ProductAttribute):
"""Arguments to create a product."""
pass
class CreateProduct(graphene.Mutation):
"""Create a product."""
product = graphene.Field(lambda: Product, description="Product created by this mutation.")
class Arguments:
input = CreateProductInput()
image = Upload(required=True)
def mutate(self, info, image, input):
data = utils.input_to_dictionary(input)
data['created_at'] = datetime.utcnow()
data['edited_at'] = datetime.utcnow()
print(data)
product = ProductModel(**data)
product.save()
return CreateProduct(product=product)
My base Graphene schema:
class Query(graphene.ObjectType):
"""Query objects for GraphQL API."""
node = graphene.relay.Node.Field()
single_product = graphene.relay.Node.Field(schema_product.Product)
all_products = MongoengineConnectionField(schema_product.Product)
class Mutations(graphene.ObjectType):
createProduct = schema_product.CreateProduct.Field()
schema = graphene.Schema(query=Query, types=[schema_product.Product], mutation=Mutations)