Flutter Image.network()加载图片报403错误

881 阅读2分钟

1. 报错403提示错误

======== Exception caught by image resource service ==================
The following NetworkImageLoadException was thrown resolving an image codec:
HTTP request failed, statusCode: 403, https://p2.music.126.net/GvYw==/xx6.jpg 
When the exception was thrown, this was the stack: 
#0      NetworkImage._loadAsync (package:flutter/src/painting/_network_image_io.dart:150:9)
<asynchronous suspension>
Image provider: NetworkImage("https://p2.music.126.net/GvYw==/xx6.jpg", scale: 1.0)
Image key: NetworkImage("https://p2.music.126.net/GvYw==/xx6.jpg", scale: 1.0)
=====================================================================================

浏览器可以正常访问图片资源,flutter使用NetworkImage加载图片报错,是因为服务器设置防伪链,导致客户端使用NetworkImage()请求图片时被服务器拒绝;

2. 解决方法

2.1 导入dio请求依赖

    ```
dependencies:
  flutter:
    sdk: flutter
    cupertino_icons: ^1.0.2
    dio: ^5.3.3

2.2 创建一个自定义请求类封装dio,使其get请求接口暴露给使用者,来达到我们想要的自定义模拟请求头

    import 'dart:typed_data';
    import 'package:dio/dio.dart';

    const String bytes_user_agent =
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36 Edg/118.0.2088.76";

    class SSJRequestManager {
      final Dio _dio = Dio();

      Dio getDio() {
        return _dio;
      }

      SSJRequestManager();

      // 获取二进制数据
      Future<Uint8List> get_bytes(String path, Map<String, dynamic> params) async {
        var options = Options(
            method: "GET",
            responseType: ResponseType.bytes,
            headers: {"User-Agent": bytes_user_agent});

        return await _dio
            .get(path, queryParameters: params, options: options)
            .then((value) => value.data);
      }
    }

    final SSJRequestManager ssjRequestManager = SSJRequestManager();

2.3 在需要调用的地方使用我们定义好的get_bytes函数来获取二进制字节数据,用于构建图片,这里要注意的是 responseType:ResponseType.bytes 这一句,设置返回响应体为我们想要的 Uint8List 数据类型然后我们在需要构建组件的地方,使用 FutureBuilder 来异步构建组件模块

    import 'dart:convert';
    import 'package:flutter/material.dart';
    class IndexBanner extends StatelessWidget {
      const IndexBanner({super.key});
      @override
      Widget build(BuildContext context) {
        return const BannerContent();
      }
    }
    class BannerContent extends StatefulWidget {
      const BannerContent({super.key});
      @override
      State<BannerContent> createState() => _BannerContentState();
    }

    class _BannerContentState extends State<BannerContent> {
      final _bannerData = [];
      int bannerCount = 0;
      @override
      void initState() {
        // TODO: implement initState
        super.initState();
      }
      @override
      Widget build(BuildContext context) {
        return Container(
          alignment: Alignment.topLeft,
          height: 200,
          child: _bannerData.length > 0? Swiper(
            itemBuilder: (BuildContext context,int index){
              return Container(
                padding: const EdgeInsets.all(8),
                child: Container(
                  clipBehavior: Clip.hardEdge,
                  decoration: BoxDecoration(
                    borderRadius: BorderRadius.circular(8)
                  ),
                  child: FutureBuilder(
                     future: ssjRequestManager.get_bytes(_bannerData[index].pic,{}),
                     builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
                       if(snapshot.connectionState == ConnectionState.done){
                         return Image.memory(snapshot.data,fit: BoxFit.fill);
                       }else {
                         return const Icon(Icons.file_download);
                         // return const Icon();
                       }
                     }
                  ),
                )
              );
            },
            itemCount: _bannerData.length,
            // itemCount: 5,
            loop: true, // 无缝循环
            autoplay: true, // 自动播放
            pagination: const SwiperPagination(
              margin:  EdgeInsets.only(bottom: 20),
              builder: DotSwiperPaginationBuilder(
                size: 8, // 未选中的大小
                activeSize: 8, // 选中的大小
                color: Color.fromRGBO(0, 0, 0, 0.08), // 未选中的颜色
                activeColor: Color.fromRGBO(255, 0, 0, 1)
              )
            ),
            control: null,
          ): const SizedBox(
            height: 200,
            child: Text(''),
          ),
        );
      }
    }

3. 删除NetWorkImage请求时添加的user-agent方法

删除user-agent链接

注:

转载链接:blog.csdn.net/qianxiamuxi…