如何在Flutter Web中支持HTTP头部的NetworkImage

3

我试图在Flutter Web中获取一些需要添加头部信息的网络图片。我尝试使用cached_network_image: ^2.5.1插件,但它并不完全支持Web平台。同时,在Flutter Web上运行时,使用Image.network似乎也不能添加头部信息。这两种方法都可以在Android版本中成功运行。

enter image description here
environment:
  sdk: ">=2.7.0 <3.0.0"

Doctor summary (to see all details, run flutter doctor -v):
[√] Flutter (Channel stable, 2.0.4, on Microsoft Windows [Version 10.0.19042.985], locale en-US)
[√] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
[√] Chrome - develop for the web
[√] Android Studio (version 4.1.0)
[√] IntelliJ IDEA Ultimate Edition (version 2020.1)
[√] Connected device (3 available)

• No issues found!
3个回答

5

使用 cached_network_image: 3.0.0 版本,我可以通过使用 CachedNetworkImageProvider 类添加标头来使其正常工作。

CachedNetworkImageProvider(
              "${IOConfig.apiUrl}",
              headers: {"Authorization": "Bearer $apiToken",
                "Access-Control-Allow-Headers": "Access-Control-Allow-Origin, Accept"}                                                
             ,imageRenderMethodForWeb: ImageRenderMethodForWeb.HttpGet)

我必须使用参数来改变 Web 渲染器才能启动它。

flutter run -d chrome --web-renderer html 

1
这就是它!但我使用了 CachedNetworkImage 和 _imageRenderMethodForWeb_。 需要导入包:cached_network_image_platform_interface/cached_network_image_platform_interface.dart - agfe2

1
最有可能,这种限制是由于img HTML元素本身的定制能力降低所致。幸运的是,还有许多其他方法来显示网络图片 - 这里只列举了两个例子:

使用http软件包:

  void loadImageV1(String url, Map<String, String>? headers) async {
    final res = await http.get(Uri.parse(url), headers: headers);
    final blob = html.Blob([res.bodyBytes]);
    setState(() {
      _url = html.Url.createObjectUrlFromBlob(blob);
    });
  }

或者使用浏览器提供的fetch API
  void loadImageV2(String url, Map<String, String>? headers) async {
    final res = await html.window.fetch(url, {'method': 'GET', 'headers': headers});
    final blob = await res.blob();
    setState(() {
      _url = html.Url.createObjectUrlFromBlob(blob);
    });
  }

现在我们可以使用生成的合成URL来构造Image.Network

以下是完整的演示:

import 'dart:html' as html;
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';

void main() => runApp(DemoApp());

class DemoApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Network Image Demo',
      home: NextLabPage(),
    );
  }
}

const imgUrl = 'https://robohash.org/1234';
const imgHeaders = {'Accept': 'image/*', 'Accept-language': 'en'};

class NextLabPage extends StatefulWidget {
  @override
  _NextLabPageState createState() => _NextLabPageState();
}

class _NextLabPageState extends State<NextLabPage> {
  String? _url;

  @override
  void initState() {
    super.initState();
    loadImageV1(imgUrl, imgHeaders);
  }

  @override
  void dispose() {
    if (_url != null) html.Url.revokeObjectUrl(_url!);
    super.dispose();
  }

  void loadImageV1(String url, Map<String, String>? headers) async {
    final res = await http.get(Uri.parse(url), headers: headers);
    final blob = html.Blob([res.bodyBytes]);
    setState(() {
      _url = html.Url.createObjectUrlFromBlob(blob);
    });
  }

  void loadImageV2(String url, Map<String, String>? headers) async {
    final res = await html.window.fetch(url, {'method': 'GET', 'headers': headers});
    final blob = await res.blob();
    setState(() {
      _url = html.Url.createObjectUrlFromBlob(blob);
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Center(
        child: _url != null ? Image.network(_url!) : Text('Loading...'),
      ),
    );
  }
}


为什么要转换成Blob?我会将字节传递给内存图像,这样它就不是Web专用的了。 - EzPizza

0

不要将图像转换为Blob,我建议直接将原始字节传递给内存图像:

  Uint8List? _imageBytes;

  void loadImage(String url, Map<String, String>? headers) async {
    final res = await http.get(Uri.parse(url), headers: headers);
    setState(() {
      _imageBytes = res.bodyBytes;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Center(
        child: _imageBytes == null ? Text('Loading...') : Image.memory(_imageBytes!),
      ),
    );
  }

记得在Image中使用errorBuilder参数,以防请求失败或不包含有效图像。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接