先說(shuō)說(shuō)我為了測(cè)試文件上傳和下載做了哪些前期準(zhǔn)備吧,首先我把我的個(gè)人域名申請(qǐng)了一張ssl證書(shū)(https),然后我自己寫了一個(gè)文件上傳接口(php)。
文件下載
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart'; //這里是一個(gè)路勁功能庫(kù)
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 {
//還好我之前寫過(guò)服務(wù)端代碼,不然我根本沒(méi)有相對(duì)路勁的概念
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 { //這里根據(jù)平臺(tái)獲取當(dāng)前安裝目錄
final directory = Theme.of(context).platform == TargetPlatform.android
? await getExternalStorageDirectory()
: await getApplicationDocumentsDirectory();
return directory.path;
}
}
我是安卓手機(jī)跑的,檢驗(yàn)結(jié)果就是去查看手機(jī) 文件管理>內(nèi)部存儲(chǔ)>Android>data>你的包名>files>Download下面有沒(méi)有一個(gè)test.xlsx(報(bào)名根據(jù)你的真機(jī)調(diào)試的APP名稱去找)
講完下載,咱們?cè)賮?lái)玩上傳
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'; //強(qiáng)烈推薦的網(wǎng)絡(luò)圖片組件(加載、失敗、成功)三種展示
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監(jiān)聽(tīng),我發(fā)現(xiàn)不怎么好用,就沒(méi)去研究
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();
}
})
],
),
),
)),
),
);
}
}
你可能會(huì)想為什么我要給uploadFile三種值,第一種:沒(méi)開(kāi)始上傳 第一種:開(kāi)始上傳,第二種:上傳成功返回值(或者為錯(cuò)誤值),你可能還會(huì)想為什么要單獨(dú)再做一個(gè)加載器CircularProgressIndicator,因?yàn)橐粋€(gè)是上傳提示,一個(gè)是加載網(wǎng)絡(luò)圖片提示。
好了今天的上傳跟下載分享完畢了,踩坑感覺(jué)就是好。
應(yīng)讀者要求補(bǔ)充一下上傳代碼:
<?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));
}
?>
依賴庫(kù)文件(我就不過(guò)濾了,反正你們看著?。?/p>
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