python - 如何使用 Flutter Web 上传文件(Python 服务器)
问题描述
我正在尝试通过 Flutter 前端上传多个文件,可能会上传到 Python 服务器。我还没有找到任何关于如何通过 Flutter Web 上传文件的工作代码。我的前端代码是根据这里的答案:How to Pick files and Images for upload with flutter web
import 'package:http/http.dart' as http;
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
void main() {
/// your app lunch from here
runApp(new MaterialApp(
//// remove debug logo top left AppBar
debugShowCheckedModeBanner: false,
// application title
title: 'Hello World',
// whole content
home: TabsExample(),
));
}
class TabsExample extends StatefulWidget {
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return TabsState();
}
}
class TabsState extends State<TabsExample> {
@override
Widget build(BuildContext context) {
// TODO: implement build
return DefaultTabController(
length: 1,
child: new Scaffold(
appBar: AppBar(
title: Text('Test Tab'),
bottom: TabBar(tabs: [
Tab(
icon: Text(
'Test',
),
),
]),
),
body: TabBarView(children: [
new FileUploadWithHttp(),
]),
));
}
}
class FileUploadWithHttp extends StatefulWidget {
@override
_FileUploadWithHttpState createState() => _FileUploadWithHttpState();
}
class _FileUploadWithHttpState extends State<FileUploadWithHttp> {
PlatformFile objFile;
PlatformFile result;
void chooseFileUsingFilePicker() async {
//-----pick file by file picker,
var result = await FilePicker.platform.pickFiles(
withReadStream:
true, // this will return PlatformFile object with read stream
allowMultiple: true);
print(result.files.length);
print(result.names);
// print(result.files.first.path); //not supported on web
if (result != null) {
setState(() {
objFile = result.files[0];
//print(objFile.readStream);
});
}
}
void uploadSelectedFile() async {
//---Create http package multipart request object
final request = http.MultipartRequest(
"POST",
Uri.parse("http://localhost:8000"), // e.g. localhost
);
//-----add other fields if needed
//request.fields["id"] = "abc";
//-----add selected file with request
request.files.add(new http.MultipartFile(
"file", objFile.readStream, objFile.size,
filename: objFile.name));
//-------Send request
var resp = await request.send();
//------Read response
String result = await resp.stream.bytesToString();
//-------Your response
print(result);
print('Upload successfull!');
}
@override
Widget build(BuildContext context) {
return Container(
child: Column(
children: [
//------Button to choose file using file picker plugin
ElevatedButton(
child: Text("Choose File"),
onPressed: () => chooseFileUsingFilePicker()),
//------Show file name when file is selected
if (objFile != null) Text("File name : ${objFile.name}"),
//------Show file size when file is selected
if (objFile != null) Text("File size : ${objFile.size} bytes"),
//------Show upload utton when file is selected
ElevatedButton(
child: Text("Upload"), onPressed: () => uploadSelectedFile()),
],
),
);
}
}
根据这个建议在 python 服务器上运行它:https ://gist.github.com/UniIsland/3346170
或者我尝试过的任何其他方法都不起作用,服务器无法正确接收文件。错误信息是:
(False, "Can't find out file name...", 'by: ', ('::1', 62868, 0, 0))
有没有关于如何上传文件的直接方法(可能是代码)?或者您知道为什么会出现此错误吗?任何帮助将不胜感激!
解决方案
按照这个,它可能会帮助你。
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'dart:io';
import 'package:path/path.dart';
import 'package:dio/dio.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or simply save your changes to "hot reload" in a Flutter IDE).
// Notice that the counter didn't reset back to zero; the application
// is not restarted.
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
// This widget is the home page of your application. It is stateful, meaning
// that it has a State object (defined below) that contains fields that affect
// how it looks.
// This class is the configuration for the state. It holds the values (in this
// case the title) provided by the parent (in this case the App widget) and
// used by the build method of the State. Fields in a Widget subclass are
// always marked "final".
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
File _image;
final GlobalKey<ScaffoldState> _scaffoldstate =
new GlobalKey<ScaffoldState>();
Future getImage() async {
var image = await ImagePicker.pickImage(source: ImageSource.camera);
_uploadFile(image);
setState(() {
_image = image;
});
}
void _incrementCounter() {
setState(() {
// This call to setState tells the Flutter framework that something has
// changed in this State, which causes it to rerun the build method below
// so that the display can reflect the updated values. If we changed
// _counter without calling setState(), then the build method would not be
// called again, and so nothing would appear to happen.
_counter++;
});
}
// Methode for file upload
void _uploadFile(filePath) async {
// Get base file name
String fileName = basename(filePath.path);
print("File base name: $fileName");
try {
FormData formData =
new FormData.from({"file": new UploadFileInfo(filePath, fileName)});
Response response =
await Dio().post("http://192.168.0.101/saveFile.php", data: formData);
print("File upload response: $response");
// Show the incoming message in snakbar
_showSnakBarMsg(response.data['message']);
} catch (e) {
print("Exception Caught: $e");
}
}
// Method for showing snak bar message
void _showSnakBarMsg(String msg) {
_scaffoldstate.currentState
.showSnackBar(new SnackBar(content: new Text(msg)));
}
@override
Widget build(BuildContext context) {
// This method is rerun every time setState is called, for instance as done
// by the _incrementCounter method above.
//
// The Flutter framework has been optimized to make rerunning build methods
// fast, so that you can just rebuild anything that needs updating rather
// than having to individually change instances of widgets.
return Scaffold(
key: _scaffoldstate,
appBar: AppBar(
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text(widget.title),
),
body: Center(
// Center is a layout widget. It takes a single child and positions it
// in the middle of the parent.
child: _image == null ? Text('No image selected.') : Image.file(_image),
),
floatingActionButton: FloatingActionButton(
onPressed: getImage,
tooltip: 'Increment',
child: Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
推荐阅读
- macos - 使用 Electron-Builder 构建后运行 .dmg 应用程序会导致“应用程序意外退出”。
- powerbi - PowerBI:当满足任一 VAR 时返回计算
- php - 在 Wordpress 中调用动态数据
- javascript - 这段代码如何找到两个对象数组之间的差异?
- r - 从当地时间到国际时间?
- docker-compose - Docker 数据库迁移/部署到 DigitalOcean
- vb.net - 如何检测 webbrowser-control 中的错误
- html - 如何使用 CSS 将单行文本向上移动 10 像素或 15 像素?
- c - 如何防止这种无限循环
- python - 如何使用 python pandas 计算嵌套组比例而不丢失原始行数