当前位置: 首页 > news >正文

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,展示

         wx.compressImage({
            src: path, // 图片路径
            quality: 50, // 压缩质量
            success: (res) => {
              console.log(res, 'ressss')
            },
            fail: (err) => {
              console.log(err)
            }
          })

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

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

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

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

(1)微信小程序端

   //选择图片
   wx.chooseMedia({
      count: 1,
      mediaType: 'image',
      success: (r) => {
       //上传给node服务器进行转换
       wx.uploadFile({
            url: 'http://localhost:7001/uploadImg/api/heictoany', 
            filePath:r.tempFiles[0].tempFilePath,
            name: 'file',
            success: (res) => {
              let src = 'http://localhost:7001/MKIntouch/' ++JSON.parse(res.data).src
              //拿到地址重新下载图片
              wx.downloadFile({
                url: src, 
                success (tempR) {
                  if (tempR.statusCode === 200) {
                   //重新生成本地临时路径(用这个路径在去上传给后端可上传heic成功,也可以回显)
                    console.log(tempR.tempFilePath)
                  }
                }
              })
            }
          })

      }

(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

    const whitelist = [
        // images
        '.jpg', '.jpeg', // image/jpeg
        '.png', // image/png, image/x-png
        '.gif', // image/gif
        '.bmp', // image/bmp
        '.wbmp', // image/vnd.wap.wbmp
        '.webp',
        '.tif',
        '.psd',
        // text
        '.svg',
        '.js', '.jsx',
        '.json',
        '.css', '.less',
        '.html', '.htm',
        '.heic',
        '.HEIC',
        '.xml',
        // tar
        '.zip',
        '.gz', '.tgz', '.gzip',
        // video
        '.mp3',
        '.mp4',
        '.avi',
    ];

    exports.multipart = {
        whitelist,
        fileSize: '50mb',
    };

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

2.在router页面进行创建

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

'use strict';
module.exports = app => {
    const { router, controller } = app;
    const subRouter = router.namespace('/uploadImg');

    subRouter.post('/api/heictoany', controller.uploadImg.api.heictoany);

};

3.controller层进行业务书写

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

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

'use strict';
const egg = require('egg');
const convert = require('heic-convert');
const fs = require('fs');
const { promisify } = require('util');

const path = require('path');
const awaitWriteStream = require('await-stream-ready').write;
const senToWormhole = require('stream-wormhole');
// 时间格式化
const dayjs = require('dayjs');
const await = require('await-stream-ready/lib/await');


module.exports = class Pages extends egg.Controller {
    async heictoany() {
        const { ctx } = this;

        // 获取文件流
        const stream = await ctx.getFileStream();
        // 创建基础的目录
        const uploadBasePath = 'public/img';
        // 创建生成的基础名
        const filename = `${Date.now()}${Number.parseInt(Math.random() * 1000)}${path.extname(stream.filename).toLocaleLowerCase()}`;
        // const resultname = filename.replace(/heic/g, 'png')
        const resultname = filename.replace(/heic/g, 'jpg')
        // 生成文件夹
        const dirname = dayjs(Date.now()).format('YYYY/MM/DD');
        // 创建目录
        function mkdirsSync(dirname) {
            if (fs.existsSync(dirname)) { // fs.existsSync检测目录是否存在,存在返回true,反之亦然
                return true;
            }
            if (mkdirsSync(path.dirname(dirname))) { // 返回 path 的目录名,尾部的文件名会被忽略path.dirname('/目录1/目录2/目录3');返回'/目录1/目录2'
                fs.mkdirSync(dirname);// fs.mkdirSync同步地创建目录
                return true;
            }

        }

        mkdirsSync(path.join(uploadBasePath, dirname));// path.join,以特定的分隔符将路径连接起来
        // 生成写入路径
        const target = path.join(uploadBasePath, dirname, filename);

        console.log(path.join(uploadBasePath, dirname), '文件文件');
        // 写入流
        const writeStream = fs.createWriteStream(target);
        try {
            // 异步把文件流 写入
            await awaitWriteStream(stream.pipe(writeStream));
        } catch (err) {
            // 如果出现错误,关闭管道
            await sendToWormhole(stream);
            return Promise.reject('上传错误');
        }

        const inputBuffer = await promisify(fs.readFile)(target);
        console.log(inputBuffer, 'inputBuffer');
        const outputBuffer = await convert({
            buffer: inputBuffer, // the HEIC file buffer
            format: 'JPEG', // output format
            // format: 'PNG', // output format
        });
        console.log(outputBuffer, 'outbuffer')
        console.log(path.join(uploadBasePath, dirname, resultname), 'xxxx')
        const resultUrl = path.join(uploadBasePath, dirname, resultname);
        console.log(resultUrl, 'resultURLLLLL')
        await promisify(fs.writeFile)(resultUrl, outputBuffer);

        ctx.status = 200;
        ctx.body = {
            src: resultUrl
        };


    }
};

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

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

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

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

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

欢迎交流该问题

相关文章:

  • 数据分析 | Pandas 200道练习题,每日10道题,学完必成大神(2)
  • 2017年某高校848数据结构真题复习
  • python正态分布中的normal函数
  • 场景金融持续引发行业关注,4.0时代打造金融服务新生态
  • 大数据面试重点之mysql篇
  • 【网络安全篇】JavaSript基础内容大全
  • 【数据结构与算法】时间复杂度和空间复杂度
  • 问:毁掉一个人,有多容易?答:年龄到了就可以
  • 最新|全新风格原创YOLOv7、YOLOv5和YOLOX网络结构解析图
  • 100个Python实战项目(十二)Python 并发图像下载器
  • RocketMQ 基础模型
  • java计算机毕业设计校园快递代领系统源程序+mysql+系统+lw文档+远程调试
  • 【Python】列表list
  • 如何在自己电脑上配置开发深度学习项目(windows)
  • 麻雀优化CNN超参数用于回归MATLAB
  • python3.6+scrapy+mysql 爬虫实战
  • [ 一起学React系列 -- 8 ] React中的文件上传
  • 【技术性】Search知识
  • Angular4 模板式表单用法以及验证
  • FastReport在线报表设计器工作原理
  • HTML-表单
  • JavaScript服务器推送技术之 WebSocket
  • Java读取Properties文件的六种方法
  • Java深入 - 深入理解Java集合
  • js继承的实现方法
  • Object.assign方法不能实现深复制
  • redis学习笔记(三):列表、集合、有序集合
  • Tornado学习笔记(1)
  • 如何解决微信端直接跳WAP端
  • 赢得Docker挑战最佳实践
  • 用jQuery怎么做到前后端分离
  • 中文输入法与React文本输入框的问题与解决方案
  • 如何在 Intellij IDEA 更高效地将应用部署到容器服务 Kubernetes ...
  • ​如何防止网络攻击?
  • ​一些不规范的GTID使用场景
  • #我与Java虚拟机的故事#连载10: 如何在阿里、腾讯、百度、及字节跳动等公司面试中脱颖而出...
  • (02)Hive SQL编译成MapReduce任务的过程
  • (2022版)一套教程搞定k8s安装到实战 | RBAC
  • (33)STM32——485实验笔记
  • (C语言)fgets与fputs函数详解
  • (done) NLP “bag-of-words“ 方法 (带有二元分类和多元分类两个例子)词袋模型、BoW
  • (Redis使用系列) Springboot 使用redis实现接口幂等性拦截 十一
  • (附源码)计算机毕业设计SSM基于java的云顶博客系统
  • (含react-draggable库以及相关BUG如何解决)固定在左上方某盒子内(如按钮)添加可拖动功能,使用react hook语法实现
  • (全注解开发)学习Spring-MVC的第三天
  • (学习日记)2024.03.12:UCOSIII第十四节:时基列表
  • (原創) 是否该学PetShop将Model和BLL分开? (.NET) (N-Tier) (PetShop) (OO)
  • (原創) 未来三学期想要修的课 (日記)
  • (转)http协议
  • (转)jQuery 基础
  • .bat批处理(八):各种形式的变量%0、%i、%%i、var、%var%、!var!的含义和区别
  • .Net 4.0并行库实用性演练
  • .net Application的目录
  • .Net Core 中间件验签
  • .Net Memory Profiler的使用举例