• heic图片转换


    问题:

    heic图片在微信小程序端不能回显也不能上传成功。

    1.了解heic图

    Heic格式是苹果专门为iOS11开发的照片格式。Heic是苹果iOS和macOS的一种文件格式,用于处理图像和视频。Heic是H.264和JEP格式,取代了IOS 11系统中的原始视频和照片。Heic格式不仅可以节省内存,还可以保留原始图像质量。Heic格式是苹果iOS和iOS的特殊格式。

    heic的特点:与JPG相比,heic格式占用空间更少,图像质量更无损。HEIC格式照片支持iOS11和macOS High Sierra(10.13)及更高版本。但是这种格式不能用图片查看软件直接在Windows中打开(Windows10 RS4开始支持这种格式)。

    2.微信小程序下的回显

    heic的图片在微信小程序下,经过压缩,可以转换为jpeg,展示

    1. wx.compressImage({
    2. src: path, // 图片路径
    3. quality: 50, // 压缩质量
    4. success: (res) => {
    5. console.log(res, 'ressss')
    6. },
    7. fail: (err) => {
    8. console.log(err)
    9. }
    10. })

    注意:压缩图片在微信小程序可以回显页面,但是继续上传后端,依旧会失败

    3.解决微信小程序上传失败

    终极解决方案是后端进行转换。暂时没有找到前端能直接转换的方案,如果有,欢迎讨论

    (下面是为了上传heic图片成功,所以用本地node端测试了一下转换图片,在回传给前端,在重新上传给真正的后端转换的图片上传成功的案例)

    (1)微信小程序端

    1. //选择图片
    2. wx.chooseMedia({
    3. count: 1,
    4. mediaType: 'image',
    5. success: (r) => {
    6. //上传给node服务器进行转换
    7. wx.uploadFile({
    8. url: 'http://localhost:7001/uploadImg/api/heictoany',
    9. filePath:r.tempFiles[0].tempFilePath,
    10. name: 'file',
    11. success: (res) => {
    12. let src = 'http://localhost:7001/MKIntouch/' ++JSON.parse(res.data).src
    13. //拿到地址重新下载图片
    14. wx.downloadFile({
    15. url: src,
    16. success (tempR) {
    17. if (tempR.statusCode === 200) {
    18. //重新生成本地临时路径(用这个路径在去上传给后端可上传heic成功,也可以回显)
    19. console.log(tempR.tempFilePath)
    20. }
    21. }
    22. })
    23. }
    24. })
    25. }

    (2)node端转换heic

    主要使用插件

    GitHub - catdad-experiments/heic-convert: 🤳 convert heic/heif images to jpeg and png

    node端用了egg.js框架

    1.进行配置

    文件上传 | Egg

    egg.js内置了

    配置插件 - config.default.js

    1. const whitelist = [
    2. // images
    3. '.jpg', '.jpeg', // image/jpeg
    4. '.png', // image/png, image/x-png
    5. '.gif', // image/gif
    6. '.bmp', // image/bmp
    7. '.wbmp', // image/vnd.wap.wbmp
    8. '.webp',
    9. '.tif',
    10. '.psd',
    11. // text
    12. '.svg',
    13. '.js', '.jsx',
    14. '.json',
    15. '.css', '.less',
    16. '.html', '.htm',
    17. '.heic',
    18. '.HEIC',
    19. '.xml',
    20. // tar
    21. '.zip',
    22. '.gz', '.tgz', '.gzip',
    23. // video
    24. '.mp3',
    25. '.mp4',
    26. '.avi',
    27. ];
    28. exports.multipart = {
    29. whitelist,
    30. fileSize: '50mb',
    31. };

    如果不配置config,接收文件流会报错

    2.在router页面进行创建

    创建文件夹 - uploadImg->app,js

    1. 'use strict';
    2. module.exports = app => {
    3. const { router, controller } = app;
    4. const subRouter = router.namespace('/uploadImg');
    5. subRouter.post('/api/heictoany', controller.uploadImg.api.heictoany);
    6. };

    3.controller层进行业务书写

    要使用的插件需要利用npm下载哦

    controller新建文件夹uploadImg->app.js

    1. 'use strict';
    2. const egg = require('egg');
    3. const convert = require('heic-convert');
    4. const fs = require('fs');
    5. const { promisify } = require('util');
    6. const path = require('path');
    7. const awaitWriteStream = require('await-stream-ready').write;
    8. const senToWormhole = require('stream-wormhole');
    9. // 时间格式化
    10. const dayjs = require('dayjs');
    11. const await = require('await-stream-ready/lib/await');
    12. module.exports = class Pages extends egg.Controller {
    13. async heictoany() {
    14. const { ctx } = this;
    15. // 获取文件流
    16. const stream = await ctx.getFileStream();
    17. // 创建基础的目录
    18. const uploadBasePath = 'public/img';
    19. // 创建生成的基础名
    20. const filename = `${Date.now()}${Number.parseInt(Math.random() * 1000)}${path.extname(stream.filename).toLocaleLowerCase()}`;
    21. // const resultname = filename.replace(/heic/g, 'png')
    22. const resultname = filename.replace(/heic/g, 'jpg')
    23. // 生成文件夹
    24. const dirname = dayjs(Date.now()).format('YYYY/MM/DD');
    25. // 创建目录
    26. function mkdirsSync(dirname) {
    27. if (fs.existsSync(dirname)) { // fs.existsSync检测目录是否存在,存在返回true,反之亦然
    28. return true;
    29. }
    30. if (mkdirsSync(path.dirname(dirname))) { // 返回 path 的目录名,尾部的文件名会被忽略path.dirname('/目录1/目录2/目录3');返回'/目录1/目录2'
    31. fs.mkdirSync(dirname);// fs.mkdirSync同步地创建目录
    32. return true;
    33. }
    34. }
    35. mkdirsSync(path.join(uploadBasePath, dirname));// path.join,以特定的分隔符将路径连接起来
    36. // 生成写入路径
    37. const target = path.join(uploadBasePath, dirname, filename);
    38. console.log(path.join(uploadBasePath, dirname), '文件文件');
    39. // 写入流
    40. const writeStream = fs.createWriteStream(target);
    41. try {
    42. // 异步把文件流 写入
    43. await awaitWriteStream(stream.pipe(writeStream));
    44. } catch (err) {
    45. // 如果出现错误,关闭管道
    46. await sendToWormhole(stream);
    47. return Promise.reject('上传错误');
    48. }
    49. const inputBuffer = await promisify(fs.readFile)(target);
    50. console.log(inputBuffer, 'inputBuffer');
    51. const outputBuffer = await convert({
    52. buffer: inputBuffer, // the HEIC file buffer
    53. format: 'JPEG', // output format
    54. // format: 'PNG', // output format
    55. });
    56. console.log(outputBuffer, 'outbuffer')
    57. console.log(path.join(uploadBasePath, dirname, resultname), 'xxxx')
    58. const resultUrl = path.join(uploadBasePath, dirname, resultname);
    59. console.log(resultUrl, 'resultURLLLLL')
    60. await promisify(fs.writeFile)(resultUrl, outputBuffer);
    61. ctx.status = 200;
    62. ctx.body = {
    63. src: resultUrl
    64. };
    65. }
    66. };

    经过测试发现,只有转成jpg才可以进行重新上传到服务器。转成png,依旧无法上传到服务器

    如果是想转换给前端base64,可以继续进行转化

    1. let res = fs.readFileSync(resultUrl,'binary')
    2. const buffer = new Buffer(res, 'binary');
    3. const src = 'data: image/png;base64,' + buffer.toString('base64');

    暂时没有什么其他方法了,微信官方都推荐后端进行转换

    转换插件,会发现,如果heic图片转换时间有点慢(1.8M的heic转换启动本地的node会大概11s左右)

    欢迎交流该问题

  • 相关阅读:
    【C++天梯计划】1.1 C++初识
    源码探索之@LoadBalanced注解工作原理
    HTML5 新的语义化标签
    大数据开发工程师要求高么?有前景么
    【跟小嘉学 Rust 编程】二十九、Rust 中的零拷贝序列化解决方案(rkyv)
    MySQL 中的锁机制
    动态规划完全背包
    [附源码]Python计算机毕业设计白果园网上水果超市
    【USRP】软件无线电基础篇:无线电频谱和波段划分表
    众和策略:几点开盘和收盘股票?
  • 原文地址:https://blog.csdn.net/qq_42625428/article/details/127532801