改变世界的webp图片技术,节约你的流量和带宽

tech2024-10-14  11

痛点:

很多网站和app有高清图片展示的需求,前后端交互时有很大的流量,在线用户量大时带宽压力随之增大。目前针对图片服务的第三方,有阿里云的oss图片存储服务器,七牛云和又拍云,价格都不便宜。怎样能够少流量又高效地服务用户呢?webp图片编码技术应运而生(可能google根本没考虑这点,只是为了提高网络图片传输速度,哈哈)。

技术栈:

1.前端基于dart的flutter框架,主要用于构建android和ios移动应用软件; 2.后端基于golang的gin开发框架,负责提供webp静态资源图片。

解决方案:

1.客户端向服务器请求图片时,获取webp格式的图片,这里我请求一张大小为76kb的高清图片。 2.在flutter端展示时,我们使用CachedNetworkImage这个组件将其缓存。所见即所得,用户看到的图片都不用二次请求,直接从缓存写入相册中。这里注意一下cacheManager的用法,是一个单例对象。

abstract class BaseCacheManager { /// Creates a new instance of a cache manager. This can be used to retrieve /// files from the cache or download them online. The http headers are used /// for the maximum age of the files. The BaseCacheManager should only be /// used in singleton patterns.

flutter端webp图片展示如下:

3.然后我们在手机缓存中找到webp图片文件,通过dart的image库将其转换为png、jpg或者其他图片格式,保存至相册。

import 'package:image/image.dart' as DownloadImage;

这里我们储存为png格式,效果如下图,大小为745kb: 小结:webp图片传输大小为76kb,从手机缓存中恢复到相册.png形式,大小为745kb,节约了89.8%的流量费用,也降低了带宽压力。

示例源码:

flutter客户端

import 'dart:io'; import 'package:image/image.dart' as DownloadImage; import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:flutter_cache_manager/flutter_cache_manager.dart'; import 'package:image_gallery_saver/image_gallery_saver.dart'; import 'package:path_provider/path_provider.dart'; import 'package:permission_handler/permission_handler.dart'; void main() => runApp(EpubWidget()); class EpubWidget extends StatefulWidget { @override State<StatefulWidget> createState() { return new EpubState(); } } class EpubState extends State<EpubWidget> { final BaseCacheManager _cacheManager = DefaultCacheManager(); final String _imgUrl = 'http://192.168.0.113:8888/image/model.webp'; File _file; @override Widget build(BuildContext context) { //动态申请储存权限 PermissionHandler().checkPermissionStatus(PermissionGroup.storage).then((pStatus){ if(pStatus == PermissionStatus.granted){ debugPrint("already get the right to save image on the phone"); return; }else{ PermissionHandler().requestPermissions(<PermissionGroup>[ PermissionGroup.storage, // 在这里添加需要的权限 ]); } }); return MaterialApp( debugShowCheckedModeBanner: false, title: "Fetch Epub Example", home: new Material( child: Scaffold( body: Column( children: <Widget>[ // Image.asset('assets/img0.webp'), CachedNetworkImage( imageUrl: _imgUrl, ), Padding( padding: const EdgeInsets.only(top: 60), child: RaisedButton( onPressed: () async{ FileInfo _fromMemory = _cacheManager.getFileFromMemory(_imgUrl); DownloadImage.Image image = DownloadImage.decodeImage(File(_fromMemory.file.path).readAsBytesSync()); // Resize the image to a 120x? thumbnail (maintaining the aspect ratio). DownloadImage.Image thumbnail = DownloadImage.copyResize(image, width: 120); // Save the thumbnail as a JPG. final dir = await getApplicationDocumentsDirectory(); // _file = File('${dir.path}/thumbnail.png')..writeAsBytesSync(DownloadImage.encodePng(thumbnail)); _file = File('${dir.path}/thumbnail.png')..writeAsBytesSync(DownloadImage.encodePng(image)); final result = await ImageGallerySaver.saveFile(_file.path); print('result is $result'); setState(() { }); }, child: Text('download image'), ), ), if(_file!=null) Image.file(_file) ], ), ) ) ); } }

golang服务端

package main import ( "net/http" "github.com/gin-gonic/gin" ) func main() { router := gin.Default() router.StaticFS("/image", http.Dir("./image")) //图片model.webp保存在image文件夹下 router.Run(":8888") }

舔狗被骗了一万零八百,实在没钱吃饭了,兄弟们如果都看到这里了,麻烦打赏个10块钱,让我吃个蛋炒饭吧, 球球啦~

附言

webp转储jpg、png等任意格式图片在前端完成;而任意格式图片重新编码为webp的时间消耗较大,最好放在后台,这里借鉴一下别人的golang处理办法

golang后台任意图片转储为webp格式

最新回复(0)