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
    评论
好的,我可以为您提供一些指导和提示。在使用Flutter精美的登录页面时,需要考虑以下几个方面: 1. UI设计:为了让登录页面更加吸引人,需要考虑颜色、布局和大小等方面,以使其看起来更加整洁、美观和易于使用。 2. 动画效果:使用一些动画效果可以使您的登录页面更具生动性和活力,例如,当用户输入用户名和密码时,可以使用字符动画来显示。 3. 交互设计:用户对登录页面的交互应该是简单而直接的,包括输入框、按钮和提示信息等,需要考虑用户体验和易用性。 在开始设计和编登录页面之前,您需要首先了解Flutter的基本概念和代码结构。以下是一个简单的示例代码,展示了如何使用Flutter创建一个基本的登录页面: ```dart import 'package:flutter/material.dart'; class LoginPage extends StatefulWidget { @override _LoginPageState createState() => _LoginPageState(); } class _LoginPageState extends State<LoginPage> { TextEditingController _usernameController = TextEditingController(); TextEditingController _passwordController = TextEditingController(); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("Login Page"), ), body: Padding( padding: EdgeInsets.all(16.0), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ TextField( controller: _usernameController, decoration: InputDecoration(hintText: "Username"), ), SizedBox(height: 20), TextField( controller: _passwordController, obscureText: true, decoration: InputDecoration(hintText: "Password"), ), SizedBox(height: 20), RaisedButton( onPressed: () { // handle login }, child: Text("Login"), ) ], ), ), ); } } ``` 上面的示例中,我们创建了一个名为LoginPage的StatefulWidget,并在其状态类中定义了两个TextEditingController,用于处理用户名和密码的输入。在build方法中,我们使用Scaffold组件来创建页面的布局,包括AppBar、TextField和RaisedButton组件来处理登录。您可以根据需要更改这些组件的属性或添加其他组件来提高登录界面的美观度和交互性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值