You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中如何为URL请求添加Header以访问Token保护的PDF

问题:flutter_pdfview加载带Token认证的URL返回空PDF

我在用flutter_pdfview库从URL加载PDF,但该URL需要通过请求头携带Token(会话ID)才能访问。目前我的传参方式无效,获取到的是空PDF,以下是我的代码:

Future<File> createFileOfPdfUrl() async {
    Completer<File> completer = Completer();

    if (kDebugMode) {
      print("Start download file from internet!");
    }
    try {
      String url =
          "$customURL.pdf";
      if (kDebugMode) {
        print("url: $url");
      }

      final filename = url.substring(url.lastIndexOf("/") + 1);
      var client = HttpClient();
      HttpClientRequest request = await client.getUrl(Uri.parse(url));
      request.headers.add(
          HttpHeaders.acceptHeader,
          HeaderValue(
              "text/plain", {'APPAUTH': '${widget.authService.loginToken}'})); // 此处方式无效,得到空PDF

      var response = await request.close();
      var bytes = await consolidateHttpClientResponseBytes(response);
      var dir = await getApplicationDocumentsDirectory();

      if (kDebugMode) {
        print("Download files");
        print("${dir.path}/$filename");
      }
      File file = File("${dir.path}/$filename");

      await file.writeAsBytes(bytes, flush: true);
      completer.complete(file);
    } catch (e) {
      throw Exception('Error parsing asset file!');
    }

    return completer.future;
}

解决方案

1. 修正请求头添加方式

你错误地把自定义Token放到了Accept请求头的参数里,正确的做法是单独添加自定义请求头:

// 替换原来的header添加代码
request.headers.add('APPAUTH', widget.authService.loginToken);
// 同时设置正确的Accept头,告诉服务器你要接收PDF
request.headers.add(HttpHeaders.acceptHeader, 'application/pdf');

2. 增加响应状态校验

添加响应状态码检查,避免下载到认证失败(如401)或错误的内容:

var response = await request.close();
if (response.statusCode != HttpStatus.ok) {
  throw Exception('请求失败,状态码: ${response.statusCode}');
}

3. 完整修正后的代码

Future<File> createFileOfPdfUrl() async {
  Completer<File> completer = Completer();

  if (kDebugMode) {
    print("开始从网络下载文件!");
  }
  try {
    String url = "$customURL.pdf";
    if (kDebugMode) {
      print("url: $url");
    }

    final filename = url.substring(url.lastIndexOf("/") + 1);
    var client = HttpClient();
    HttpClientRequest request = await client.getUrl(Uri.parse(url));
    
    // 正确添加自定义Token头
    request.headers.add('APPAUTH', widget.authService.loginToken);
    // 设置接受PDF类型
    request.headers.add(HttpHeaders.acceptHeader, 'application/pdf');

    var response = await request.close();
    
    // 校验响应状态
    if (response.statusCode != HttpStatus.ok) {
      throw Exception('请求失败,状态码: ${response.statusCode}');
    }

    var bytes = await consolidateHttpClientResponseBytes(response);
    
    // 调试:打印字节长度,确认是否获取到有效内容
    if (kDebugMode) {
      print("下载字节长度: ${bytes.length}");
    }

    var dir = await getApplicationDocumentsDirectory();
    if (kDebugMode) {
      print("文件保存路径: ${dir.path}/$filename");
    }
    File file = File("${dir.path}/$filename");

    await file.writeAsBytes(bytes, flush: true);
    completer.complete(file);
  } catch (e) {
    throw Exception('处理文件时出错: $e');
  }

  return completer.future;
}

4. 替代方案:使用dio库简化下载

如果觉得原生HttpClient太繁琐,可以用dio库来处理,它对请求头和文件下载的支持更友好:

  1. 先在pubspec.yaml添加依赖:
dependencies:
  dio: ^5.4.0+1
  path_provider: ^2.1.2
  1. 实现代码:
import 'package:dio/dio.dart';
import 'package:path_provider/path_provider.dart';

Future<File> downloadPdfWithToken() async {
  Dio dio = Dio();
  String url = "$customURL.pdf";
  
  // 添加请求头
  dio.options.headers['APPAUTH'] = widget.authService.loginToken;
  dio.options.headers['Accept'] = 'application/pdf';

  var dir = await getApplicationDocumentsDirectory();
  String savePath = "${dir.path}/${url.substring(url.lastIndexOf("/") + 1)}";

  var response = await dio.download(url, savePath);
  
  if (response.statusCode != 200) {
    throw Exception('下载失败,状态码: ${response.statusCode}');
  }

  return File(savePath);
}

内容的提问来源于stack exchange,提问作者Florentin Lupascu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 21:40:52