在Flutter中如何将图像从网络保存到本地目录。
我是编码和解码图像的新手。有人能指出我正确的方向吗?
答案 0 :(得分:7)
有一个简单的答案和一个更复杂的答案。我将描述复杂的一个,然后给你一个简单的。
复杂的答案是,您可以使用NetworkImage
手动缓存图像,解析图像并获取图像流。获得图像流后,可以使用flutter的文件读取和保存将其保存到文件系统中。编写功能(this是一个很好的资源来了解更多信息) - 你还需要使用一个名为PathProvider的插件,它为iOS和Android提供了正确的路径,该路径在该链接中有所描述。您还需要跟踪您下载的所有图像,并可能在一定时间后删除它们。在使用它们创建Image
小部件之前,您还必须先阅读这些文件。
这给了你很多控制权,但是有点工作(虽然不是一个疯狂的数量,但如果你是新手,可能不是你想要做的事情,这取决于你想要保存图像的原因)
简单的答案是救援套件!其他人已经遇到过这个问题并编写了一个插件来解决它,所以你不必考虑它!
有关该插件的信息,请参阅cached_network_image package。
您需要在pubspec.yaml
dependencies:
cached_network_image: "^0.3.0"
导入它:
import 'package:cached_network_image/cached_network_image.dart';
并使用它!
new CachedNetworkImage(
imageUrl: "http://imageurl.png",
placeholder: new CircularProgressIndicator(),
errorWidget: new Icon(Icons.error),
),
请注意,此下载&显示图片 - 如果您想单独执行这些操作,可以使用new CachedNetworkImageProvider(url)
并使用new Image
进行显示。
答案 1 :(得分:6)
徘徊在代码和文档之后。我找到了适用于iOS和Android的方法和类,而且一切顺利。
帮助程序类
import 'dart:async';
import 'dart:io' as Io;
import 'package:image/image.dart';
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
import 'package:path_provider/path_provider.dart';
class SaveFile {
Future<String> get _localPath async {
final directory = await getApplicationDocumentsDirectory();
return directory.path;
}
Future<Io.File> getImageFromNetwork(String url) async {
var cacheManager = await CacheManager.getInstance();
Io.File file = await cacheManager.getFile(url);
return file;
}
Future<Io.File> saveImage(String url) async {
final file = await getImageFromNetwork(url);
//retrieve local path for device
var path = await _localPath;
Image image = decodeImage(file.readAsBytesSync());
Image thumbnail = copyResize(image, 120);
// Save the thumbnail as a PNG.
return new Io.File('$path/${DateTime.now().toUtc().toIso8601String()}.png')
..writeAsBytesSync(encodePng(thumbnail));
}
}
课程的使用
class HomePageState extends State<HomePage>{
Future<Null> _launched ;
Widget _showResult(BuildContext context, AsyncSnapshot<Null> snapshot){
if(!snapshot.hasError){
return Text('Image is saved');
}
else{
return const Text('Unable to save image');
}
}
Future<Null> _saveNetworkImage(String url) async{
try{
await SaveFile().saveImage(url);
}
on Error catch(e){
throw 'Error has occured while saving';
}
}
@override
Widget Build(BuildContext context){
return new Scaffold(
key: _scaffoldKey,
appBar: new AppBar(
title: new Text('Image'),
),
body: Column(
children: <Widget>[
IconButton(icon: Icon(Icons.save), onPressed: (){
setState(() {
_launched =_saveNetworkImage(url);
});
}),
new FutureBuilder<Null>(future: _launched ,builder: _showResult),
],
),
);
}
}
答案 2 :(得分:2)
如果您只想将图像(例如:.png)保存到设备,则可以通过简单的get(http / http.dart)和File(dart:io)轻松实现。
为此,您可以根据以下示例进行操作:
var response = await get(imgUrl);
documentDirectory = await getApplicationDocumentsDirectory();
File file = new File(
join(documentDirectory.path, 'imagetest.png')
);
file.writeAsBytesSync(response.bodyBytes);
请注意,在上述情况下,我使用了来自dart pub的“ path_provider”包。总体而言,您的导入中至少应包含以下项目:
import 'dart:io';
import 'package:http/http.dart' show get;
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
答案 3 :(得分:1)
要将网络映像保存在本地系统中,您需要使用ImagePickerSave dart插件。在pub.yaml文件中添加dart插件: image_picker_saver:^ 0.1.0 ,然后调用以下代码以保存图像。 URL是网络图像的图像URL
void _onImageSaveButtonPressed(String url) async {
print("_onImageSaveButtonPressed");
var response = await http
.get(url);
debugPrint(response.statusCode.toString());
var filePath = await ImagePickerSaver.saveFile(
fileData: response.bodyBytes);
var savedFile= File.fromUri(Uri.file(filePath));
}
答案 4 :(得分:0)
您可以使用image_downloader。
Environment.DIRECTORY_DOWNLOADS
或指定位置。通过调用inExternalFilesDir()
,不需要指定权限。callback()
,您可以获取进度状态。以下是最简单的示例。它将被保存。
await ImageDownloader.downloadImage(url);
答案 5 :(得分:0)
我在执行此操作时遇到很多麻烦,因此我想通过一个简单的示例来详细说明上述答案,该示例在启动时下载文件,然后将其保存到本地目录中。我用注释//%%%
标记了几行,以显示可以在应用程序第二次运行时被注释掉的行。 (因为它不需要下载即可显示...它已经在设备本身上:
import 'package:flutter/material.dart';
import 'package:http/http.dart' show get;
import 'dart:io';
import 'package:path_provider/path_provider.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Test Image',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Test Image'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
initState() {
_downloadAndSavePhoto();
super.initState();
}
_downloadAndSavePhoto() async {
// Get file from internet
var url = "https://www.tottus.cl/static/img/productos/20104355_2.jpg"; //%%%
var response = await get(url); //%%%
// documentDirectory is the unique device path to the area you'll be saving in
var documentDirectory = await getApplicationDocumentsDirectory();
var firstPath = documentDirectory.path + "/images"; //%%%
//You'll have to manually create subdirectories
await Directory(firstPath).create(recursive: true); //%%%
// Name the file, create the file, and save in byte form.
var filePathAndName = documentDirectory.path + '/images/pic.jpg';
File file2 = new File(filePathAndName); //%%%
file2.writeAsBytesSync(response.bodyBytes); //%%%
setState(() {
// When the data is available, display it
imageData = filePathAndName;
dataLoaded = true;
});
}
String imageData;
bool dataLoaded = false;
@override
Widget build(BuildContext context) {
if (dataLoaded) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
// imageData holds the path AND the name of the picture.
Image.file(File(imageData), width: 600.0, height: 290.0)
],
),
),
);
} else {
return CircularProgressIndicator(
backgroundColor: Colors.cyan,
strokeWidth: 5,
);
}
}
}
这是我的pubspec.yaml文件:
http: ^0.12.0+2
path_provider: 1.5.0
答案 6 :(得分:0)
您可以使用此功能从相机上载并获取Url(下载)图像 firebase-storage
Future _upIm()async {
final StorageReference firebaseStorageRef =
FirebaseStorage.instance.ref().child(DateTime.now().toString());
final StorageUploadTask task =
firebaseStorageRef.putFile(_storedImage);
var downUrl=await (await task.onComplete).ref.getDownloadURL();
var url =downUrl.toString();
print(url);
setState(() {
uploadImage=url;
});
}
答案 7 :(得分:0)
受Paras启发,CacheManager.getInstance()已弃用
final DefaultCacheManager defaultCacheManager = DefaultCacheManager();
final fileInfo = await defaultCacheManager.getFileFromCache(imageUrl);
ImageGallerySaver.saveImage(image);
下面是saveImage函数
// save raw data to gallery with permission
static Future<void> saveImage(Uint8List image) async {
try {
if (Platform.isIOS) {
await PermissionHandler().requestPermissions([PermissionGroup.photos]);
PermissionStatus permission = await PermissionHandler().checkPermissionStatus(PermissionGroup.photos);
if (permission == PermissionStatus.granted) {
} else {
throw 'denied';
}
} else if (Platform.isAndroid) {
await PermissionHandler().requestPermissions([PermissionGroup.storage]);
PermissionStatus permission = await PermissionHandler().checkPermissionStatus(PermissionGroup.storage);
if (permission == PermissionStatus.granted) {
} else {
throw 'denied';
}
}
await ImageGallerySaver.saveImage(image);
} catch (e) {
throw e;
}
}
答案 8 :(得分:-1)
关注此网址flutter save network image。
代码段
import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:io';
import 'package:path_provider/path_provider.dart';
import 'package:http/http.dart' as http;
class NetworkToLocalImage extends StatefulWidget{
String url;
NetworkToLocalImage(this.url);
@override
_LoadImages createState() => new _LoadImages(url);
}
class _LoadImages extends State<NetworkToLocalImage>{
String url;
String filename;
var dataBytes;
_LoadImages(this.url){
filename = Uri.parse(url).pathSegments.last;
downloadImage().then((bytes){
setState(() {
dataBytes = bytes;
});
});
}
Future<dynamic> downloadImage() async {
String dir = (await getApplicationDocumentsDirectory()).path;
File file = new File('$dir/$filename');
if (file.existsSync()) {
print('file already exist');
var image = await file.readAsBytes();
return image;
} else {
print('file not found downloading from server');
var request = await http.get(url,);
var bytes = await request.bodyBytes;//close();
await file.writeAsBytes(bytes);
print(file.path);
return bytes;
}
}
@override
Widget build(BuildContext context) {
// TODO: implement build
if(dataBytes!=null)
return new Image.memory(dataBytes);
else return new CircularProgressIndicator();
}
}
答案 9 :(得分:-3)