Skip to content

Web文件上传

Published:

基础文件上传

使用 HTML 的<input type="file" />元素是实现文件上传最基础的方式。

import React, { useState } from "react";

const FileDemo: React.FC = (props) => {
  return (
    <input
      type="file"
      accept="image/*"
      // multiple
      onChange={async (e) => {
        const file = e.target.files?.[0];

        console.log("@file", file);
        console.log("@文件名字", file?.name);
        console.log("@文件大小", (file?.size ?? 0) / 1000 / 1000 + "MB");
      }}
    />
  );
};
export default FileDemo;

上面代码中:

如果我们希望将得到的File转为可以显示的DataURL。则:

const convertFile2DataUrl = (file: File) => {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    // 处理加载完成事件
    reader.onload = (event: ProgressEvent<FileReader>) => {
      if (!event.target?.result) {
        reject(new Error("Failed to read file"));
        return;
      }

      if (typeof event.target.result !== "string") {
        reject(new Error("Invalid result type"));
        return;
      }

      resolve(event.target.result);
    };

    // 处理错误
    reader.onerror = () => {
      reject(new Error("Error reading file: " + reader.error?.message));
    };

    // 处理中止
    reader.onabort = () => {
      reject(new Error("File reading aborted"));
    };

    try {
      reader.readAsDataURL(file);
    } catch (error) {
      reject(
        new Error("Failed to start reading file: " + (error as Error).message)
      );
    }
  });
};

动态文件上传

动态文件上传,表示我们随时动态创建或者引用一个隐藏在页面上的input元素。这样我们就是可以随时动态的控制文件上传,并可以更容易的定制上传组件的样式。

import React, { useState } from "react";

const FileDemo = () => {
  const inputRef = React.useRef<HTMLInputElement>(null);

  const handleUpload = async () => {
    const onChange = async (e: Event) => {
      const file = (e.target as HTMLInputElement).files?.[0];
      console.log("@file", file);
      console.log("@文件名字", file?.name);
      console.log("@文件大小", (file?.size ?? 0) / 1000 / 1000 + "MB");
    };

    if (!inputRef.current) return;
    inputRef.current.onchange = onChange;
    inputRef.current?.click();
    // 或
    // const input = document.createElement("input");
    // input.type = "file";
    // input.accept = "image/*";
    // input.onchange = onChange;

    // input.click();
  };

  return (
    <div>
      <div
        className="bg-yellow-400 cursor-pointer p-2 rounded"
        onClick={handleUpload}
      >
        点击上传文件
      </div>
      <input
        ref={inputRef}
        type="file"
        accept="image/*"
        style={{ display: "none" }}
      />
    </div>
  );
};

export default FileDemo;

上传进度监控

上传文件监控我们是基于 axios 实现的。

axios.post("/api", file, {
  onUploadProgress: progressEvent => {
    if (progressEvent.total) {
      console.log(progressEvent.loaded, progressEvent.total);
    }
  },
});

大文件分片上传

暂停和断点续传


Previous Post
前端pdf预览方案
Next Post
React+signature_pad实现Web签名板