HEIC是苹果自己的格式,用来存储iOS摄像头拍摄的高分辨率图像,但我会将其存储在后台JPG格式,因为HEIC在大多数浏览器中都不会显示,甚至在Safari中也不会。
溶液1
我尝试了以下转换:
const buffer = Buffer.from(await file.arrayBuffer())
const d = heicConvert({ buffer, format: 'JPEG' })
const imgBase64 = btoa(
d.reduce((data, byte) => `${data}${String.fromCharCode(byte)}`, '')
)
但因为我使用Next.js,所以它与之不兼容。
Failed to compile.
./node_modules/libheif-js/libheif/libheif.js
Module not found: Can't resolve 'fs' in '/Users/janoskukoda/Workspace/tikex/portal/team/node_modules/libheif-js/libheif'
溶液2
我也试过这个:
export default uploadImage
const buffer = await file.arrayBuffer()
const image = sharp(buffer)
const metadata = await image.metadata()
if (metadata.format === 'heic') {
// Convert the image to JPG
const jpgBuffer = await image.jpeg().toBuffer()
// Encode the JPG image as a base64 string
const imgBase64 = btoa(
jpgBuffer.reduce((data, byte) => `${data}${String.fromCharCode(byte)}`, '')
)
}
但是我不能编译,似乎sharp
不建议在客户端使用。
你还有别的办法吗?
不管怎样,想法来了:https://itnext.io/tackling-iphone-or-ipad-images-support-in-browser-8e3e64e9aaa1
如果你给我看一个解决方案使用无服务器的API,这也是可以的。这是重要的文件来自html输入元素。
溶液3
import loadImage from 'blueimp-load-image'
convertedImage = await new Promise((resolve, reject) => {
loadImage(
propsAndFile.file,
resolve,
{ orientation: true, canvas: true },
reject
)
})
2条答案
按热度按时间wrrgggsh1#
在得到答案之前:您永远不能信任客户端上传的数据-您必须始终使用用户无法访问的流程(后端流程)进行验证/转换,以确保数据的有效性:即使有适当的机制来验证接收到的网络请求是否来自您站点上经过身份验证的用户,任何用户仍然可以使用开发人员工具来执行任意JavaScript,并发送任何类型的网络请求以及他们想要的任何有效负载。
关于iOS设备和从文件输入获取JPEG而不是HEIF:你不需要自己做这些-iOS可以为你做。
<input type="file">
元素支持accept
属性,该属性可用于限制可上载的文件媒体类型的种类:更多信息请参阅MDN文档文章中关于<input type="file">
的 * 限制可接受的文件类型 * 部分。下面的示例显示了如何使用该属性。当iOS用户选择输入时,他们可以选择使用相机拍摄照片或从照片库中选择一张照片。在这两种情况下,iOS将自动执行必要的JPEG文件转换(例如,即使从照片库中选择的图像是HEIF格式)。当您在iOS设备上尝试使用HEIF编码的图像时,该示例演示了这一点:
7fhtutme2#
通过在终端中运行以下命令安装heic2jpeg库:
将heic2jpeg库导入React组件:
通过调用heic2jpeg库的convert方法并将HEIC文件作为参数传入,将HEIC文件转换为JPG:
然后,您可以使用jpegData创建一个新的JPG文件或在img元素中显示它:
注意,heic2jpeg库要求canvas和process模块在全局上下文中可用,因此您可能也需要在应用程序中包含这些模块。