先说说我为了测试文件上传和下载做了哪些前期准备吧,首先我把我的个人域名申请了一张ssl证书(https),然后我自己写了一个文件上传接口(php)。
文件下载
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart'; //这里是一个路劲功能库
import 'package:dio/dio.dart';
class FilePage extends StatefulWidget {
@override
State<FilePage> createState() {
// TODO: implement createState
return _FilePage();
}
}
class _FilePage extends State<FilePage>{
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(title: Text("文件下载"),),
body: Column(
children: <Widget>[
Builder(builder: (context){
return FlatButton(
child: Text("文件下载"),
onPressed: () async {
//还好我之前写过服务端代码,不然我根本没有相对路劲的概念
String _localPath = (await _findLocalPath()) + '/Download';
Response responce = await Dio().download("https://yujun.store/test.xlsx", _localPath+"/test.xlsx");
if(responce.statusCode == 200){
Scaffold.of(context).showSnackBar(
SnackBar(content: Text("下载成功"))
);
}
},
);
})
],
),
);
}
Future<String> _findLocalPath() async { //这里根据平台获取当前安装目录
final directory = Theme.of(context).platform == TargetPlatform.android
? await getExternalStorageDirectory()
: await getApplicationDocumentsDirectory();
return directory.path;
}
}
我是安卓手机跑的,检验结果就是去查看手机 文件管理>内部存储>Android>data>你的包名>files>Download下面有没有一个test.xlsx(报名根据你的真机调试的APP名称去找)
讲完下载,咱们再来玩上传
import 'package:flutter/material.dart';
import 'dart:io';
import 'package:file_picker/file_picker.dart';
import 'package:dio/dio.dart';
import 'dart:convert';
import 'package:cached_network_image/cached_network_image.dart'; //强烈推荐的网络图片组件(加载、失败、成功)三种展示
class FilePickerDemo extends StatefulWidget {
@override
_FilePickerDemoState createState() => new _FilePickerDemoState();
}
class _FilePickerDemoState extends State<FilePickerDemo> {
String uploadFile = "";
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold(
appBar: new AppBar(
title: const Text('文件选择(上传)例子'),
),
body: new Center(
child: new Padding(
padding: const EdgeInsets.only(left: 10.0, right: 10.0),
child: new SingleChildScrollView(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
onPressed: () async {
File file = await FilePicker.getFile(type: FileType.CUSTOM,fileExtension: "jpg");
setState(() {
uploadFile = "0";
});
var name = file.path.substring(file.path.lastIndexOf("/") + 1, file.path.length);
var postData = FormData.fromMap({
"thumb": await MultipartFile.fromFile(
file.path, filename: name)
});
// var responce = await Request().getInstance().upload("https://yujun.store/upload.php",postData, (send, total){
// print("$send $total");
// });//这里我用的我自己封装的上传方法,print("$send $total");这里是Dio的onSendProgress监听,我发现不怎么好用,就没去研究
var responce = await Dio().post("https://yujun.store/upload.php",data:postData,onSendProgress: (int sent, int total) {
print("$sent $total"); //send是上传的大小 total是总文件大小
},);
var uploadData = jsonDecode(responce.toString());
setState(() {
uploadFile = uploadData['url'];
});
},
child: Text(
"添加图片"
),
),
Builder(builder: (context){
if(uploadFile.isNotEmpty){
return Container(
width: 300.0,
height: 200.0,
child: uploadFile == '0'?
Center(
child: SizedBox(
width: 80.0,
height: 80.0,
child: CircularProgressIndicator(),
),
)
:
CachedNetworkImage(
imageUrl: uploadFile,
placeholder: (context, url) => Center(
child: SizedBox(
width: 80.0,
height: 80.0,
child: CircularProgressIndicator(),
),
),
errorWidget: (context, url, error) => Icon(Icons.error),
)
);
}else{
return Container();
}
})
],
),
),
)),
),
);
}
}
你可能会想为什么我要给uploadFile三种值,第一种:没开始上传 第一种:开始上传,第二种:上传成功返回值(或者为错误值),你可能还会想为什么要单独再做一个加载器CircularProgressIndicator,因为一个是上传提示,一个是加载网络图片提示。
好了今天的上传跟下载分享完毕了,踩坑感觉就是好。
应读者要求补充一下上传代码:
<?php
header("Access-Control-Allow-Origin:*");
header('Access-Control-Allow-Methods:POST');
header('Access-Control-Allow-Headers:x-requested-with, content-type');
header('Content-type:text/json');
$file = $_FILES;
$arr=explode('.', $file['thumb']['name']);
$extend = ".".$arr[count($arr)-1];
$filePath = "/uploads/".str_replace($extend, "", $file['thumb']['name']).time().$extend;
$path = "uploads/".str_replace($extend, "", $file['thumb']['name']).time().$extend;
if(move_uploaded_file($file['thumb']["tmp_name"],iconv("UTF-8", "gbk",$path)) == false){
echo json_encode(array('code' => -1, 'msg' => '文件上传失败'));
}else{
echo json_encode(array('code' => 1, 'msg' => '文件上传成功', 'url' =>'https://'.$_SERVER['HTTP_HOST'].$filePath));
}
?>
依赖库文件(我就不过滤了,反正你们看着取):
cupertino_icons: ^0.1.2
shared_preferences: ^0.5.4+8
dio: ^3.0.0
provider : ^3.2.0
flutter_screenutil: ^1.0.1
dio_log: 1.3.3
dynamic_list_view: ^0.1.9
flutter_downloader: ^1.4.0
path_provider: ^1.5.0
permission_handler: ^4.1.0
file_picker: ^1.4.3+2
cached_network_image: ^2.0.0