How to check file MIME type with javascript before upload?

前端 未结 9 2095
挽巷
挽巷 2020-11-22 03:50

I have read this and this questions which seems to suggest that the file MIME type could be checked using javascript on client side. Now, I understand that the real validati

9条回答
  •  清酒与你
    2020-11-22 04:39

    Here is a Typescript implementation that supports webp. This is based on the JavaScript answer by Vitim.us.

    interface Mime {
      mime: string;
      pattern: (number | undefined)[];
    }
    
    // tslint:disable number-literal-format
    // tslint:disable no-magic-numbers
    const imageMimes: Mime[] = [
      {
        mime: 'image/png',
        pattern: [0x89, 0x50, 0x4e, 0x47]
      },
      {
        mime: 'image/jpeg',
        pattern: [0xff, 0xd8, 0xff]
      },
      {
        mime: 'image/gif',
        pattern: [0x47, 0x49, 0x46, 0x38]
      },
      {
        mime: 'image/webp',
        pattern: [0x52, 0x49, 0x46, 0x46, undefined, undefined, undefined, undefined, 0x57, 0x45, 0x42, 0x50, 0x56, 0x50],
      }
      // You can expand this list @see https://mimesniff.spec.whatwg.org/#matching-an-image-type-pattern
    ];
    // tslint:enable no-magic-numbers
    // tslint:enable number-literal-format
    
    function isMime(bytes: Uint8Array, mime: Mime): boolean {
      return mime.pattern.every((p, i) => !p || bytes[i] === p);
    }
    
    function validateImageMimeType(file: File, callback: (b: boolean) => void) {
      const numBytesNeeded = Math.max(...imageMimes.map(m => m.pattern.length));
      const blob = file.slice(0, numBytesNeeded); // Read the needed bytes of the file
    
      const fileReader = new FileReader();
    
      fileReader.onloadend = e => {
        if (!e || !fileReader.result) return;
    
        const bytes = new Uint8Array(fileReader.result as ArrayBuffer);
    
        const valid = imageMimes.some(mime => isMime(bytes, mime));
    
        callback(valid);
      };
    
      fileReader.readAsArrayBuffer(blob);
    }
    
    // When selecting a file on the input
    fileInput.onchange = () => {
      const file = fileInput.files && fileInput.files[0];
      if (!file) return;
    
      validateImageMimeType(file, valid => {
        if (!valid) {
          alert('Not a valid image file.');
        }
      });
    };
    

提交回复
热议问题