These links

– 01 Simple drag-and-drop uploads and progress bars

V1.3: File type verification

In the previous article, we implemented a basic file upload and made some simple optimizations on top of it: drag upload, which requires attention to drag related events, and a progress bar, which can be implemented using Axios’ onUploadProgress.

Today we will further optimize this little file upload demo by adding the ability to verify file types.

Basic edition: suffix

As you can imagine, component libraries provide a beforeUpload method to verify the suffix of a file, so let’s verify the file type this way first.

First let’s look at the data type of file:

As you can see, there is a name field here, and we can verify this by intercepting the last.xxx:

const filename = fileRef.value.name;
const ext = filename.split(".").pop();
Copy the code

Up to this point, a simple suffix validation has been implemented, but there are some pitfalls in validating files based on suffixes: for example, the user deliberately changes the file’s suffix.

Here, the user changes the apk file suffix to PNG, and it can be seen that both file.type and name are regarded as pictures. If the user changes the file type to APK again after passing the verification of the front end, an unsafe file may be uploaded to the server.

Those interested can check out BurpSuite.

Upgraded version: binary

Before implementing the functionality, we can either perform winhex or simply install a hexdump in vscode to see how different files differ.

JPG

PNG

conclusion

The other types are similar, and interested readers can check for themselves. Here is the direct conclusion:

  • JPG: the file header is FF D8 FF
  • PNG: The file header is 89 50 4E 47
  • GIF: the file header is 47 49 46 38

Reference: standard code for various types of file headers

Here we take GIF as an example to illustrate.

The first step is to encapsulate a method that converts the file header to a hexadecimal format. See the comments for details:

const blobToString = (blob: Blob): Promise<string> => {
  return new Promise(resolve= > {
    const reader = new FileReader();
    reader.onload = () = > {
      const result = (reader.result as string)
        .split("")
				// Convert to asC code
        .map((v: string) = > v.charCodeAt(0))
				// Convert to hexadecimal
        .map((v: number) = > v.toString(16))
				/ / filling 0
        .map((v: string) = > v.padStart(2."0"))
        .join("");
      resolve(result);
    };
    reader.readAsBinaryString(blob);
  });
};
Copy the code

So if we want to determine if a file is a GIF, just pass in the first four bytes:

const isGif = async (file: File): Promise<boolean> => {
  const ret = await blobToString(file.slice(0.4));
  return ret === "47 49 46 38";
};
Copy the code

Now let’s change the PNG file to GIF and test it again:

conclusion

The demo now has drag-and-drop uploading, a progress bar, and file type verification, which is starting to take shape. In future articles, we will show you how to implement functions such as large file slice uploading, file second uploading, and breakpoint uploading.

So let’s call it a day and look forward to the next meeting