Flutter文件上傳和下載

先說(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
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • vsftpd.conf 部分:文件格式(5)索引 返回主要內(nèi)容 名稱 vsftpd.conf - vsftpd的配...
    張龍象閱讀 2,507評(píng)論 0 1
  • 前言~前段時(shí)間做項(xiàng)目用到了bootstrap里中的文件上傳控件,對(duì)此特定寫這篇文章,講述一下bootstra...
    Sugge丶R閱讀 2,842評(píng)論 0 0
  • 《出塞》 (唐)王之渙 黃河遠(yuǎn)上白云間,一片孤城萬(wàn)仞山。 羌笛何須怨楊柳,春風(fēng)不度玉門關(guān)。 《出塞》是王之渙的得意...
    晨曦文集閱讀 310評(píng)論 1 7
  • 想起來(lái)當(dāng)時(shí)我說(shuō)暗戀單戀也是愛(ài)情被室友嘲笑了……
    __Sapiosexual閱讀 99評(píng)論 0 0
  • 今天,又幫一位系里大四的學(xué)姐拿實(shí)習(xí)材料給老師,又想起去年給大四學(xué)姐拿實(shí)習(xí)材料,心里想了很多。 今年我...
    繽果依欣閱讀 418評(píng)論 0 1

友情鏈接更多精彩內(nèi)容