简体   繁体   中英

How to display jpeg image loaded from .NET Core API in Flutter?

I'm trying to display a jpeg image loaded from a .NET Core web API. However, it seems like I'm doing something wrong with the encoding. Sometimes I get no errors, but the image is invisible and not displayed. Sometimes I get the following error:

Could not instantiate image codec.

I have tried several approaches to display the image with no success.

The web API response including the jpeg image:

在此处输入图像描述

Screenshot of app page to display the image:

在此处输入图像描述

The code which loads the image from the API:

Future<Uint8List> _loadFileBytes(String fileId) async {
    var bytesResponse = await fileHttpService.getFileBytes(fileId);
    if (bytesResponse.statusCode != 200) _handlePhotoLoadError();
    var bytesStr = bytesResponse.body;
    var bytes = utf8.encode(bytesStr);
    return bytes;
  }

The Widget code that receives the jpeg image bytes in the photo property trying to display it:

import 'package:flutter/material.dart';
import 'package:knowe_personnelledger_mobile/models/CADPhotoModel.dart';
import 'package:image/image.dart' as imageUtils;

class CADPhotoView extends StatefulWidget {
  final CADPhotoModel photo;

  CADPhotoView({@required this.photo});

  @override
  CADPhotoViewState createState() => CADPhotoViewState();
}

class CADPhotoViewState extends State<CADPhotoView> {
  double displayHeight;
  double displayWidth;

  @override
  void initState() {
    displayHeight = 1;
    displayWidth = 1;
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    displayHeight = MediaQuery.of(context).size.height;
    displayWidth = MediaQuery.of(context).size.width;
    return Container(
        child: Stack(
      children: <Widget>[
        Row(
            mainAxisSize: MainAxisSize.max,
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: <Widget>[
              Flexible(
                  flex: 18,
                  child: Container(
                    decoration: BoxDecoration(
                        borderRadius: BorderRadius.all(
                            Radius.circular(displayWidth * 0.1)),
                        boxShadow: [
                          BoxShadow(
                              blurRadius: displayWidth * 0.05,
                              color: Color.fromRGBO(0, 0, 0, 0.5),
                              offset: Offset(
                                  displayWidth * 0.01, displayWidth * 0.025))
                        ]),
                    child: ClipRRect(
                        borderRadius: BorderRadius.all(
                            Radius.circular(displayWidth * 0.015)),
                        child: _futureBuildImage()),
                  )),
            ]),
      ],
    ));
  }

  void deleteButtonPressed() {
    showMessageDialog("", "Säker på att du vill radera fotot?");
    print("Delete button pressed!!!");
  }

  void showMessageDialog(String title, String body) {
    try {
      showDialog(
          context: context,
          builder: (BuildContext context) {
            return AlertDialog(
              title: new Text(body),
              content: Row(
                mainAxisSize: MainAxisSize.max,
                mainAxisAlignment: MainAxisAlignment.start,
                crossAxisAlignment: CrossAxisAlignment.center,
                children: <Widget>[
                  Expanded(
                    child: FlatButton(
                      onPressed: deleteDialogYesPressed,
                      child: Text("Radera"),
                    ),
                  ),
                  Expanded(
                      child: FlatButton(
                    onPressed: deleteDialogNoPressed,
                    child: Text("Avbryt"),
                  ))
                ],
              ),
            );
          });
    } catch (e) {
      print(e.toString());
    }
  }

  void deleteDialogYesPressed() {
    Navigator.pop(context);
  }

  void deleteDialogNoPressed() {
    Navigator.pop(context);
  }

  Widget _futureBuildImage() {
    var futureBuilder = FutureBuilder<Widget>(
      future: _decodeImage(),
      initialData: Container(),
      builder: _createImage,
    );
    return futureBuilder;
  }

  Future<Widget> _decodeImage() async {
    try {
      var byteData =
          await (await decodeImageFromList(widget.photo.bytes)).toByteData();
      var bytes = byteData.buffer.asUint8List();
      var image = Image.memory(bytes);

      return image;
    } catch (e) {
      return Container();
    }
  }

  Widget _createImage(BuildContext context, AsyncSnapshot<Widget> snapshot) {
    if (snapshot.connectionState == ConnectionState.none ||
        snapshot.connectionState == ConnectionState.active ||
        snapshot.connectionState == ConnectionState.waiting)
      return Container();
    else if (snapshot.connectionState == ConnectionState.done)
      return snapshot.data;
    else
      return Container();
  }
}

If you wonder why I encode the byte string with utf8, it's just another approach I have tried. I have no clue what I should do to display the image received in the web API response.

This is driving me nuts. Thanks for the help!

After fidgeting with different approaches I finally found a very simple solution. I don't understand why I didn't get this to work this way from the beginning. It was very simple. Here are the steps for others who might encounter the same problem:

Step 1, get the bytes by the Response.bodyBytes property:

Future<Uint8List> _loadFileBytes(String fileId) async {
    var bytesResponse = await fileHttpService.getFileBytes(fileId);
    if (bytesResponse.statusCode != 200) _handlePhotoLoadError();
    var bytes = bytesResponse.bodyBytes;
    return bytes;
  }

Step 2, just pass the int array to the Image.memory() method.

child: Image.memory(widget.photo.bytes)

I feel like an idiot now. Hopefully this can help others at least facing the same problem. Derp.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM