flutter web如何写一个上传文件的页面

在Flutter Web中创建一个上传文件的页面

第一种:flutter html库操作

(2024.5.9测试)

pubspec.yaml引入包:

environment:
  sdk: '>=2.19.1 <3.0.0'
dependencies:
  flutter:
    sdk: flutter
  http: 0.13.6
  http_parser: 4.0.2
  get: 4.6.5

dart页面:

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'dart:html' as html;
import 'dart:typed_data';
import 'dart:async';
import 'dart:convert';
import 'package:http_parser/http_parser.dart';
import 'package:http/http.dart' as http;

class FileUploadWeb extends StatefulWidget {
  const FileUploadWeb({super.key});

  
  State<FileUploadWeb> createState() => _FileUploadWebState();
}

class _FileUploadWebState extends State<FileUploadWeb> {

  late List<int> _selectedFile;
  late Uint8List _bytesData;
  late String _base64Encoded; // 文件base64编码


  void _handleResult(Object result) {
    setState(() {
      _bytesData = const Base64Decoder().convert(result.toString().split(",").last);
      _base64Encoded = const Base64Encoder().convert(_bytesData);
      _selectedFile = _bytesData;
    });
  }

  Future<void> _startWebFilePicker() async { // 选取文件
    html.FileUploadInputElement uploadInput = html.FileUploadInputElement();
    uploadInput.multiple = true;
    uploadInput.draggable = true;
    uploadInput.onChange.listen((e) {
      final files = uploadInput.files;
      final file = files![0];
      final reader = html.FileReader();
      reader.onLoadEnd.listen((e) {
        if (reader.result != null) {
          _handleResult(reader.result!);
        } else {
          print('选取文件失败');
        }
      });
      reader.readAsDataUrl(file);
    });
    uploadInput.click();
  }

  Future<void> _makeRequestByGetHttp() async { // get库
    var file = MultipartFile(_selectedFile, filename: "file.jpg");
    var data = FormData({
      'xxx1':'yyy1',
      '_base64Encoded':_base64Encoded,
      'file':file,
    });

    await GetConnect().post("http://127.0.0.1/savefile/",data);
  }

  Future<void> _makeRequestByHttp() async { // http库

    var url = Uri.parse("http://127.0.0.1/savefile/");
    var request = http.MultipartRequest("POST", url);
    var file = http.MultipartFile.fromBytes('file', _selectedFile,
        contentType: MediaType('application', 'octet-stream'),
        filename: "file_up"
    );
    request.files.add(file);

    request.send().then((response) {
      print("test");
      print(response.statusCode);
      if (response.statusCode == 200) {
        print("Uploaded!");
      };
    });

  }

  
  Widget build(BuildContext context) {
    // TODO: implement build

    return SafeArea(
      child: Scaffold(
        appBar: AppBar(
          title: const Text('file upload webpage'),
        ),
        body: Form(
          child: Padding(
            padding: const EdgeInsets.only(top: 16.0, left: 28),
            child: SizedBox(
                width: 350,
                child: Column(
                    children: [
                      MaterialButton(
                        color: Colors.pink,
                        elevation: 8,
                        highlightElevation: 2,
                        shape: RoundedRectangleBorder(
                            borderRadius: BorderRadius.circular(8)),
                        textColor: Colors.white,
                        onPressed: _startWebFilePicker,
                        child: const Text('select a file'),
                      ),
                      const Divider(
                        color: Colors.teal,
                      ),
                      MaterialButton(
                        color: Colors.pink,
                        elevation: 8,
                        highlightElevation: 2,
                        shape: RoundedRectangleBorder(
                            borderRadius: BorderRadius.circular(8)),
                        textColor: Colors.white,
                        onPressed: _makeRequestByHttp,
                        child: const Text('send file to server by http'),
                      ),
                      const Divider(
                        color: Colors.teal,
                      ),
                      MaterialButton(
                        color: Colors.pink,
                        elevation: 8,
                        highlightElevation: 2,
                        shape: RoundedRectangleBorder(
                            borderRadius: BorderRadius.circular(8)),
                        textColor: Colors.white,
                        onPressed: _makeRequestByGetHttp,
                        child: const Text('send file to server by gethttp'),
                      ),
                    ]
                )
            ),
          ),
        ),
      ),
    );
  }
}

效果图:
http库
get库

第二种:可以结合Flutter的UI组件和JavaScript互操作来实现文件上传功能。

以下是一个基本的步骤指南,用于在Flutter Web应用中创建一个文件上传页面:

  1. 创建Flutter UI
    使用Flutter的UI组件(如ButtonText等)来创建你的上传页面。你可以使用Button来触发文件选择对话框和上传过程。

  2. 添加文件选择逻辑
    由于Flutter的Dart代码本身不直接支持文件选择对话框,你需要使用JavaScript来实现这一功能。你可以通过dart:html库的window对象来调用JavaScript函数。

  3. 使用JavaScript选择文件
    index.html文件中添加一个隐藏的<input type="file">元素,并通过JavaScript代码来触发其点击事件,从而打开文件选择对话框。然后,你可以读取选定的文件内容,并将其发送到Flutter Dart代码中。

  4. 文件上传到服务器
    一旦你在Dart代码中接收到文件内容,你可以使用HTTP请求(如dart:http库或第三方库如dio)将文件上传到服务器。注意,由于Flutter Web的限制,你可能需要使用JavaScript的fetch API或XMLHttpRequest来执行HTTP请求。

  5. 错误处理和用户反馈
    在整个过程中添加适当的错误处理逻辑,并向用户提供有关上传进度的反馈。

下面是一个简化的示例代码片段,展示了如何在Flutter Web中结合Dart和JavaScript来实现文件上传:

Flutter Dart代码(main.dart)

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

void main() {
  runApp(MyApp());

  // 监听来自JavaScript的消息
  html.window.onMessage.listen((event) {
    // 处理从JavaScript发送过来的文件内容或上传结果
    // ...
  });
}

class MyApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('File Upload')),
        body: Center(
          child: ElevatedButton(
            onPressed: () {
              // 调用JavaScript函数来触发文件选择对话框
              html.window.callMethod('triggerFileSelect', []);
            },
            child: Text('Select File'),
          ),
        ),
      ),
    );
  }
}

index.html(添加JavaScript代码):

<!DOCTYPE html>
<html>
<head>
  <!-- ... 其他头部信息 ... -->
  <script defer src="main.dart.js" type="application/javascript"></script>
  <script>
    function triggerFileSelect() {
      // 创建一个隐藏的input元素来触发文件选择对话框
      var input = document.createElement('input');
      input.type = 'file';
      input.click();

      input.onchange = function(e) {
        var file = e.target.files[0];
        if (file) {
          // 使用FileReader读取文件内容,或使用FormData上传文件
          // 然后将文件内容或上传结果发送到Flutter Dart代码
          // ...
        }
      };
    }
  </script>
</head>
<body>
  <!-- Flutter应用的根元素 -->
  <div id="flutter-app"></div>
  <script>
    // 初始化Flutter应用
    // ...
  </script>
</body>
</html>

请注意,上述代码只是一个概念性示例,并未包含完整的文件上传逻辑。你需要根据实际需求来实现文件读取、上传到服务器以及处理结果等逻辑。此外,由于Flutter Web的限制和不断发展,某些功能可能不如原生Web开发那样直接可用,因此你可能需要更深入地了解Web开发和JavaScript编程来充分利用Flutter Web的功能。

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值