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

原文链接:download and save image to file in Flutter - 原文作者 saurabhsinghaswal
本文采用意译的方式

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

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

我们将使用下面的依赖:

步骤一:创建基本布局

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

相关代码如下:

dart 复制代码
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),
          ),
        ),
      ),
    );
  }
}

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

bash 复制代码
<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 版本:

bash 复制代码
android {  
  // 更改这里...  
  compileSdkVersion 33  
  
  ndkVersion flutter.ndkVersion  
  
  compileOptions {  
    sourceCompatibility JavaVersion.VERSION_1_8  
    targetCompatibility JavaVersion.VERSION_1_8  
  }
bash 复制代码
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 中下载并保存图像到文件

相关代码如下:

dart 复制代码
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 频道和文章,但是没人能简洁地描述怎么去做下载图像文件这件事情,但是现在我做到了。现在,到你们来尝试了。

相关推荐
你的乔克叔叔1 天前
四大组件-Activity
android
aqi001 天前
FFmpeg开发笔记(九十二)基于Kotlin的开源Android推流器StreamPack
android·ffmpeg·kotlin·音视频·直播·流媒体
stringwu1 天前
一个bug 引发的Dart 与 Java WeakReference 对比探讨
flutter
是一碗螺丝粉1 天前
React Native 运行时深度解析
前端·react native·react.js
Jing_Rainbow1 天前
【前端三剑客-9 /Lesson17(2025-11-01)】CSS 盒子模型详解:从标准盒模型到怪异(IE)盒模型📦
前端·css·前端框架
爱泡脚的鸡腿1 天前
uni-app D6 实战(小兔鲜)
前端·vue.js
青年优品前端团队1 天前
🚀 不仅是工具库,更是国内前端开发的“瑞士军刀” —— @qnvip/core
前端
北极糊的狐1 天前
Vue3 中父子组件传参是组件通信的核心场景,需遵循「父传子靠 Props,子传父靠自定义事件」的原则,以下是资料总结
前端·javascript·vue.js
看到我请叫我铁锤1 天前
vue3中THINGJS初始化步骤
前端·javascript·vue.js·3d
q***25211 天前
SpringMVC 请求参数接收
前端·javascript·算法