【问题标题】:Detect within the browser if the image uploaded is of correct format在浏览器中检测上传的图片格式是否正确
【发布时间】:2024-01-11 03:03:01
【问题描述】:

我有一个 file.svg 图像,我将文件重命名为 file.jpg

现在在浏览器中打开这个 jpg 文件肯定不会预览我的图像。所以我正在尝试检测通过输入表单上传的jpg图像是否实际上是浏览器中的jpg。

我尝试以 base64 格式读取文件,但找不到任何内容。有一种方法可以检测 jpg 图像是否被截断 这是对该文章的参考 js check if an image truncated/corrupted data

如何检测图片的类型是否正确,扩展名也是如此?

【问题讨论】:

标签: javascript file-upload browser base64


【解决方案1】:

仅通过查看文件名来查找 mime 类型是不安全的。 您应该通过读取文件内容开头的签名字节来找到文件的确切 MIME 类型。

使用this list,您可以找到签名-mime 类型配对。

我在下面编写了一个示例代码,您可以在其中检查所选文件是否为 是否是有效的 jpeg 文件。 JPEG有一个简单的签名,如果文件的前2个字节是0xFF和0xD8你可以说这个文件是一个jpeg文件。 (请查看列表以获取更完整的签名信息)。

document.querySelector('input').addEventListener('change', function() 
{
	var reader = new FileReader();
	reader.onload = function()
	{
		var bytes = new Uint8Array(this.result);
		if ((bytes[0] == 0xFF) && (bytes[1] == 0xD8))
			console.log("this is a valid jpeg file");
		else
			console.log("this does not look like a jpeg file");
	}
	reader.readAsArrayBuffer(this.files[0]);
});
<input type="file">

【讨论】:

    【解决方案2】:

    在输入上添加事件处理程序 onChange,如下所示:

    <input type="file" id="file_uploader" />
    

    然后在 javascript 中添加一个事件处理程序,它将监听该输入的变化:

    const file_input = document.getElementById(("file_uploader")
    
    file_input.addEventListener("change", handleChange)
    

    这将自动将event 传递给handleChange,因此您可以实际引用它:

    const handleChange = e => {
        const name = e.targe.file[0].name
        // name = filename.extnesion
        const extension = name.split(".")[1]
    }
    

    Split 方法将给出一个包含 2 个字符串的数组 - . 之前的字符串 - 文件名,. 之后的字符串 - 扩展名。

    【讨论】:

    • 我正在尝试检测图像是否损坏。
    • 所以检查扩展不会让您确认图像实际上是 jpg?
    • 我想我几年前做过类似的事情——从二进制数据中获取扩展名。我确定您可以在 javascript 中获取图像的二进制数据,但不确定从中提取扩展名。让我谷歌一下
    • 是的,我们可以获得 base64 字符串,甚至我也在尝试找出一种方法来检测 base64 格式。我确信这是可能的,因为有一个网站 canva.com 检测并提示错误
    【解决方案3】:

    正如 Alper Cinar 所提到的,读取扩展名并不安全,以及我们如何读取起始字节来识别 mime 类型。我想添加一个小代码 sn-p 不仅可以识别 jpg 的 mime 类型,还可以识别 gif 和 pngs

          const blob = files[0];
          const fileReader = new FileReader();
          fileReader.readAsArrayBuffer(blob);
          fileReader.onloadend = (e) => {
            const arr = (new Uint8Array(<any>e.target.result)).subarray(0, 4);
            let header = '';
            for (let i = 0; i < arr.length; i++) {
              header += arr[i].toString(16);
            }
            console.log(header);
            let type: any;
            switch (header) {
              case '89504e47':
                type = 'image/png';
                break;
              case '47494638':
                type = 'image/gif';
                break;
              case 'ffd8ffe0':
              case 'ffd8ffe1':
              case 'ffd8ffe2':
              case 'ffd8ffe3':
              case 'ffd8ffe8':
                type = 'image/jpeg';
                break;
              default:
                type = 'unknown';
                break;
            }
            console.log(type);
    
          };
    

    详细参考 How to check file MIME type with javascript before upload?

    【讨论】:

      最近更新 更多