原文链接:download and save image to file in Flutter - 原文作者 saurabhsinghaswal

本文采用意译的方式

Flutter 中下载并保存图片为文件_Flutter

任何应用程序都可以执行的最简单的活动之一是将互联网图片下载到文件系统中。

我们将学习怎么保存图片到本地的设备中,比如手机。开始之前,我们假设我们知道图片的 URL,我们会先下载图像,然后将其保存在相册或者指定的位置。

我们将使用下面的依赖:

  • flutter_file_dialog
  • path_provider
  • HTTP

步骤一:创建基本布局

我们创建一个很简单的布局,用来展示来自 URL 的图片:

Flutter 中下载并保存图片为文件_flutter_02

相关代码如下:

import 'package:flutter/material.dart';

void main() {
  runApp(const App());
}

class App extends StatelessWidget {
  const App({super.key});
  
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Save image to disk',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MainScreen(),
    );
  }
}

class MainScreen extends StatelessWidget {
  static const _url = 'https://dosomthings.com/wp-content/uploads/2022/07/dc0a7e44e96647848177c8afd4bdabdd.png';
  
  const MainScreen({super.key});
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Save image to disk'),
        centerTitle: true,
        backgroundColor: Color(0xFFe91e63),
        actions: [
          IconButton(
            onPressed: () {
              // 后面我们会在这里添加方法
            },
            icon: const Icon(Icons.save, color: Colors.white,),
          ),
        ],
      ),
      body: Center(
        child: Container(
          padding: const EdgeInsets.only(
            left: 24.0,
            right: 24.0,
          ),
          child: ClipRect(
            borderRadius: BorderRadius.circular(30.0),
            child: Image.network(_url),
          ),
        ),
      ),
    );
  }
}

步骤二:授权并在安卓中设定下载和保存图片的配置

<manifest xmlns:android="http://schemas.android.com/apk/res/android"  
package="com.example.saveimage">  
  <uses-permission android:name="android.permission.INTERNET"/>  
  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />  
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />  
  <application>

然后,我们更新 compileSdkVersionminSdkVersion 版本:

android {  
  // 更改这里...  
  compileSdkVersion 33  
  
  ndkVersion flutter.ndkVersion  
  
  compileOptions {  
    sourceCompatibility JavaVersion.VERSION_1_8  
    targetCompatibility JavaVersion.VERSION_1_8  
  }
defaultConfig {  
  // TODO: 指定你自己独一无二的应用 ID (https://developer.android.com/studio/build/application-id.html).  
  applicationId "com.example.saveimage"  
  
  // 更改这里
  minSdkVersion 19  
  
  targetSdkVersion flutter.targetSdkVersion  
  versionCode flutterVersionCode.toInteger()  
  versionName flutterVersionName  
}

步骤三:从 URL 中下载并保存图像到文件

相关代码如下:

import 'dart:math';
import 'package:flutter/material.dart';
import 'dart:io';
import 'package:flutter_file_dialog/flutter_file_dialog.dart';
import 'package:http/http.dart' as http;
import 'package:path_provider/path_provider.dart';

void main() {
  runApp(const App())
}

class App extends StatelessWidget {
  const App({super.key});
  
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Save image to disk',
      home: MainScreen(),
    );
  }
}

class MainScreen extends StatelessWidget {
  static const _url = 'https://dosomthings.com/wp-content/uploads/2023/07/How-to-download-and-save-image-to-file-in-FlutterDosomthings.com_-1024x576.png';
  var random = Random();
  
  Future<void> _saveImage(BuildContext context) async {
    final ScaffoldMessenger = ScaffoldMessager.of(context);
    late String message;
    
    try {
      // 下载图片
      final http.Response response = await http.get(Uri.parse(_url));
      
      // 获取临时的文件夹
      final dir = await getTemporaryDirectory();
      
      // 创建一个图像名称
      var filename = '${dir.path}/SaveImage${random.nextInt(100)}.png';
      
      // 保存到文件系统
      final file = File(filename);
      await file.writeAsBytes(response.bodyBytes);
      
      // 询问用户是否保存它
      final params = SaveFileDialogParams(sourceFilePath: file.path);
      final finalPath = await FlutterFileDialog.saveFile(params: params);
      
      if(filePath != null) {
        message = 'Image saved to disk'
      }
    } catch (e) {
      message = e.toString();
      scaffoldMessager.showSnackBar(SnackBar(
        content: Text(
          message,
          style: TextStyle(
            fontSize: 12,
            color: Colors.white,
            fontWeight: FontWeight.bold
          ),
        ),
        backgroundColor: Color(0xFFe91e63),
      ));
    }
    if(message != null) {
      scaffoldMessenger.showSnackBar(SnackBar(
        content: Text(
          message,
          style: TextStyle(
            fontSize: 12,
            color: Colors.white,
            fontWeight: FontWeight.bold,
          ),
        ),
        backroundColor: Color(0xFFe91e63),
      ));
    }
  }
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Save image to disk'),
        centerTitle: true,
        backgroundColor: Color(0xFFe91e63),
        actions: [
          IconButton(
            onPressed: () {
              _saveImage(context);
            },
            icon: const Icon(Icons.save, color: COlors.white,),
          ),
        ],
      ),
      body: Center(
        child: Container(
          padding: const EdgetInsets.only(
            left: 24.0,
            right: 24.0,
          ),
          child: ClipRect(
            borderRadius: BorderRadius.circular(30.0),
            child: Image.network(_url),
          ),
        ),
      ),
    );
  }
}

输出

效果截图如下:

effect_01

effect_02

effect_03

总结

在这篇文章中,我们已经学习了怎么用 Flutter 下载并保存图片到文件中。通过根据上面的步骤,我们可以整合图片下载和保存的功能到 Flutter 应用程序中,这将为离线查看图像和用户驱动的图像保存功能提供了可能性。

希望读者已经理解怎么下载图像。准确说,我也是在查阅了很多 youtube 频道和文章,但是没人能简洁地描述怎么去做下载图像文件这件事情,但是现在我做到了。现在,到你们来尝试了。