欧美成人精品手机在线观看_69视频国产_动漫精品第一页_日韩中文字幕网 - 日本欧美一区二区

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

你還不知道的WEB瀏覽器大文件上傳

admin
2025年3月31日 23:51 本文熱度 229

說起文件上傳,在我們的開發(fā)中是繞不過去的話題。但要是碰到幾十 MB 甚至 GB 級別的大文件,傳統(tǒng)上傳方式就有點 “拉胯” 了。今天就給大伙嘮嘮前端大文件上傳,講講它的原理、能解決啥問題、有哪些關鍵功能,再給大家推薦一個超實用的大文件上傳庫,讓大文件上傳不再是難題。

一、大文件上傳是啥?

(一)大文件上傳的定義

簡單來說,大文件上傳就是把個頭很大的文件,從咱們的客戶端,像瀏覽器啥的,傳到服務器上。這些大文件要是用傳統(tǒng)上傳方法,很容易出現(xiàn)上傳失敗、網(wǎng)絡超時,還可能把服務器資源占得死死的。所以,大文件上傳一般得靠分片上傳、斷點續(xù)傳、并行上傳這些技術,才能順順利利完成。

(二)大文件上傳解決的問題

  1. 網(wǎng)絡不穩(wěn)定:網(wǎng)絡這東西,時好時壞。大文件上傳的時候,網(wǎng)絡要是波動或者斷了,很容易就上傳失敗。大文件上傳技術就能應對這種情況,保證上傳能完成。
  2. 服務器資源限制:大文件上傳要是處理不好,服務器的內(nèi)存和 CPU 就遭老罪了,搞不好服務器都得崩潰。用對技術,就能減少對服務器資源的占用,讓服務器穩(wěn)穩(wěn)地運行。
  3. 用戶體驗:有了上傳進度展示、斷點續(xù)傳這些功能,用戶能隨時知道上傳到啥程度了,就算上傳中斷,也不用從頭再來,體驗感直接拉滿。
  4. 文件完整性驗證:文件傳輸?shù)臅r候,數(shù)據(jù)有可能損壞或者丟失。大文件上傳技術有文件完整性驗證,能保證上傳的文件和原來的一模一樣。

(三)大文件上傳對比普通文件上傳的優(yōu)勢

  1. 能處理大文件:普通文件上傳碰到 GB 級別的大文件,基本就歇菜了。大文件上傳用分片技術,再大的文件都能搞定。
  2. 斷點續(xù)傳:普通文件上傳中斷了就得重新開始,大文件上傳能接著沒傳完的地方繼續(xù),省時間又省帶寬。
  3. 并行上傳:大文件上傳可以把文件分成好多片同時上傳,速度 “蹭蹭” 往上漲。
  4. 優(yōu)化資源利用:分片上傳后,服務器每次處理的文件片段小,內(nèi)存占用就少,服務器性能也能提升。
  5. 精準進度監(jiān)控:大文件上傳能更準確地顯示上傳進度,用戶心里有數(shù)。

二、前端實現(xiàn)大文件上傳的關鍵要點

從前端角度看,要實現(xiàn)大文件上傳,得搞定下面這些關鍵功能:

(一)文件分片

把大文件按照固定大小,比如 1MB 或者 5MB,切成一個個小文件,也就是分片。這可以用 File API 里的 File.slice () 方法來實現(xiàn)。

(二)分片上傳

用 XMLHttpRequest 或者 Fetch API,把每個分片一個一個傳到服務器。為了更快,還能同時上傳好幾個分片,也就是并行上傳。

(三)斷點續(xù)傳

上傳要是中斷了,前端得記住哪些分片已經(jīng)傳了。下次接著傳沒傳完的。這得前端和服務器一起配合,服務器一般會記錄已經(jīng)上傳的分片信息,像文件哈希值或者分片索引。

(四)上傳進度監(jiān)控

通過 XMLHttpRequest 的 progress 事件,或者 Fetch API 的 ReadableStream,實時監(jiān)控上傳進度。然后算出已經(jīng)上傳的百分比,展示給用戶。

(五)文件完整性校驗

文件上傳完了,前端算一下文件的哈希值,比如 MD5 或者 SHA-256,再和服務器那邊校驗一下,保證文件沒出問題。這得用 FileReader 讀取文件內(nèi)容來生成哈希值。

(六)錯誤處理與重試機制

上傳的時候難免會遇到網(wǎng)絡錯誤、服務器錯誤啥的。前端得有一套完善的錯誤處理機制,每個分片還要有重試機制,保證上傳失敗的分片能重新傳。

(七)并發(fā)控制

要控制好同時上傳的分片數(shù)量,不然太多請求會占滿帶寬,服務器也扛不住??梢杂藐犃谢蛘?Promise 池來管理并發(fā)上傳任務。

(八)用戶體驗優(yōu)化

得給用戶一個清晰直觀的界面反饋,像進度條、上傳速度、剩余時間這些都得展示出來。另外,還要支持拖拽上傳、文件選擇、批量上傳這些實用功能。

(九)安全性考慮

為了防止有人上傳惡意文件,得校驗文件類型,限制文件大小。要是有敏感數(shù)據(jù),就用 HTTPS 這些加密方式傳輸。

三、寶藏大文件上傳庫 ——enlarge - file - upload

自己從頭寫一個大文件上傳庫,難度可不小,要實現(xiàn)這么多功能,短時間內(nèi)根本搞不定。給大家推薦一個超好用的庫,叫 enlarge - file - upload。上面說的這些功能,它都實現(xiàn)了,不管你用 vue2、vue3、react,還是 jquery 原生 js 開發(fā)項目,都能直接用,真正做到開箱即用。

下面講講它在不同環(huán)境里咋用:

(一)安裝

npm install enlarge-file-upload

安裝很簡單,就按常規(guī)的 npm 安裝方式就行。在項目目錄下打開命令行,輸入npm install enlarge-file-upload,等安裝完,就能在項目里用這個庫了。具體安裝命令也可以去 npm 官網(wǎng)瞅瞅:www.npmjs.com/package/enl…

(二)參數(shù)介紹

這個庫的參數(shù)挺多,能滿足各種項目需求。詳細的參數(shù)說明可以看官方文檔。這里給大家講講常用的幾個參數(shù):

  • file:這個是要上傳的文件對象,必須得有。你選好要上傳的文件,獲取到的文件對象就填這兒。
  • serverUrl:這是服務器接收文件上傳的接口地址,得填對,不然文件傳不到服務器上。
  • onProgress:這是個回調(diào)函數(shù),用來監(jiān)聽上傳進度。上傳的時候,它會實時被觸發(fā),通過它能拿到當前的上傳進度百分比,方便展示給用戶看。
  • onSuccess:文件上傳成功了,就會執(zhí)行這個回調(diào)函數(shù)。你可以在里面給用戶提示上傳成功,或者更新一下頁面狀態(tài)啥的。
  • onError:要是上傳出錯了,這個回調(diào)函數(shù)就會被調(diào)用,它會帶著錯誤信息,方便你排查問題。

(三)使用案例

  1. jquery 原生 js 中使用示例
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>文件上傳</title>
  </head>
  <script src="https://cdn.jsdelivr.net/npm/enlarge-file-upload/dist/upload.min.js"></script>
  <!-- 引入 Axios 庫,用于發(fā)送 HTTP 請求 -->
  <script src="https://cdn.jsdelivr.net/npm/axios"></script>

  <body>
    <input type="file" id="fileInput" />
    <button id="pauseButton">暫停上傳</button>
    <button id="resumeButton">繼續(xù)上傳</button>
    <div id="progress">上傳進度:0%</div>
    <div id="speed">上傳速度:0 MB/s</div>
    <script>
      // 定義上傳函數(shù)
      async function uploadFunction({ chunk, index, hash, cancelToken }) {
        const formData = new FormData();
        formData.append("chunk", chunk);
        formData.append("hash", hash);
        formData.append("index", index);
        await axios.post("http://localhost:3000/api/users", formData, {
          cancelToken,
        });
      }

      // 使用示例
      const config = {
        chunkSize: 5 * 1024 * 1024, // 5MB
        concurrency: 5,
        maxRetries: 3,
        // startOffset: 6, // 從索引為10的切片位置開始傳
        // includeChunks:[1,6], // 只上傳索引為1和6的切片,只有startOffset為0或空時才生效
        uploadFunction,
        onProgress: (progress) => {
          document.getElementById(
            "progress"
          ).innerText = `上傳進度:${state.progress.toFixed(2)}%`;
        },
        onSuccess: () => {
          console.log("上傳完畢");
        },
        onSpeed: (speed) => {
          document.getElementById("speed").innerText = `上傳速度:${speed}`;
        },
      };

      const { upload, pause, resume, state } = createUploader(config);
      const fileInput = document.getElementById("fileInput");
      fileInput.addEventListener("change", () => {
        const file = fileInput.files[0];
        upload(file);
      });
      // 暫停上傳
      document.getElementById("pauseButton").addEventListener("click", () => {
        pause();
      });
      // 繼續(xù)上傳
      document.getElementById("resumeButton").addEventListener("click", () => {
        resume();
      });
    </script>
  </body>
</html>

</html>

在這個例子里,先引入了jquery庫和enlarge-file-upload庫。頁面加載完后,給上傳按鈕綁定了點擊事件。點按鈕的時候,就去獲取文件輸入框里選的文件。要是有文件,就創(chuàng)建EnlargeFileUpload實例,把文件對象、服務器上傳接口地址,還有各種回調(diào)函數(shù)傳進去,最后調(diào)用start方法開始上傳文件。

  1. 在 vue3 中使用
<template>
    <div>
        <input type="file" @change="handleFileChange">
        <button @click="uploadFile">上傳文件</button>
    </div>
</template>

<script setup>
import EnlargeFileUpload from 'enlarge-file-upload';

const fileRef = ref(null);
const handleFileChange = (e) => {
    fileRef.value = e.target.files[0];
};

const uploadFile = () => {
    if (fileRef.value) {
        const uploader = new EnlargeFileUpload({
            file: fileRef.value,
            serverUrl: 'http://your-server-url.com/upload',
            onProgress: (progress) => {
                console.log(`上傳進度: ${progress}%`);
            },
            onSuccess: () => {
                console.log('文件上傳成功');
            },
            onError: (error) => {
                console.error('文件上傳失敗', error);
            }
        });
        uploader.start();
    }
};
</script>

在 vue3 項目里,用ref定義了一個fileRef來存選的文件。文件選擇框內(nèi)容變了,handleFileChange函數(shù)就把選的文件賦值給fileRef。點上傳按鈕的時候,看看fileRef有沒有值,有值就創(chuàng)建EnlargeFileUpload實例開始上傳文件,還設置了上傳進度、成功和失敗的回調(diào)函數(shù)。

  1. 在 vue2 中使用?
<template>
  <div>
    <input type="file" @change="handleFileChange" />
    <button @click="handlePause">暫停上傳</button>
    <button @click="handleResume">繼續(xù)上傳</button>
    <div>上傳進度:{{ progress.toFixed(2) }}%</div>
    <div>上傳速度:{{ speed }}</div>
  </div>
</template>

<script>
import Vue from "vue";
import createUploader from "enlarge-file-upload";
import axios from "axios";

export default Vue.extend({
  data() {
    return {
      progress: 0, // 進度
      speed: "0 MB/s", // 速度
      uploader: null, // 上傳器實例
    };
  },
  methods: {
    // 定義上傳函數(shù)
    async uploadFunction({ chunk, index, hash, cancelToken }) {
      const formData = new FormData();
      formData.append("chunk", chunk);
      formData.append("hash", hash);
      formData.append("index", index.toString());
      await axios.post("http://localhost:3000/api/users", formData, {
        cancelToken,
      });
    },

    // 文件選擇處理
    handleFileChange(event) {
      const file = event.target.files?.[0];
      if (file && this.uploader) {
        this.uploader.upload(file);
      }
    },

    // 暫停上傳
    handlePause() {
      if (this.uploader) {
        this.uploader.pause();
      }
    },

    // 繼續(xù)上傳
    handleResume() {
      if (this.uploader) {
        this.uploader.resume();
      }
    },
  },
  created() {
    const uploaderConfig = {
      chunkSize: 5 * 1024 * 1024, // 5MB
      concurrency: 5,
      maxRetries: 3,
      uploadFunction: this.uploadFunction,
      onProgress: (progressValue) => {
        this.progress = progressValue;
      },
      onSuccess: () => {
        console.log("上傳完畢");
      },
      onSpeed: (speedValue) => {
        this.speed = speedValue;
      },
    };

    // 創(chuàng)建上傳器實例
    this.uploader = createUploader(uploaderConfig);
  },
});
</script>

<style scoped></style>

vue2 項目里,在data里定義了file變量存文件。handleFileChange方法獲取選的文件,點上傳按鈕的時候,要是file有值,就創(chuàng)建EnlargeFileUpload實例上傳文件,設置好回調(diào)函數(shù)處理上傳過程里的各種情況。

  1. React 中使用示例
import React, { useRef, useMemo } from'react';
import EnlargeFileUpload from 'enlarge-file-upload';

const FileUploadComponent = () => {
    const fileInputRef = useRef(null);

    const uploadFile = () => {
        const file = fileInputRef.current.files[0];
        if (file) {
            const uploader = useMemo(() => new EnlargeFileUpload({
                file: file,
                serverUrl: 'http://your-server-url.com/upload',
                onProgress: (progress) => {
                    console.log(`上傳進度: ${progress}%`);
                },
                onSuccess: () => {
                    console.log('文件上傳成功');
                },
                onError: (error) => {
                    console.error('文件上傳失敗', error);
                }
            }), [file]);
            uploader.start();
        }
    };

    return (
        <div>
            <input type="file" ref={fileInputRef} />
            <button onClick={uploadFile}>上傳文件</button>
        </div>
    );
};

export default FileUploadComponent;

React 項目里,用useRef創(chuàng)建了fileInputRef來引用文件輸入框。點上傳按鈕的時候,從fileInputRef里拿選的文件。為了防止組件重新渲染的時候重復創(chuàng)建EnlargeFileUpload實例,用useMemo來創(chuàng)建上傳實例,設置好回調(diào)函數(shù)。最后在頁面里渲染文件輸入框和上傳按鈕。

  1. 封裝為 react Hooks
import React, { useState, useMemo } from "react";
import createUploader from "enlarge-file-upload";
import type { Config, UploadOptions } from "enlarge-file-upload";
import axios from "axios";

const FileUpload = () => {
  const [progress, setProgress] = useState(0);
  const [speed, setSpeed] = useState("0 MB/s");

  // 定義上傳函數(shù)
  async function uploadFunction({
    chunk,
    index,
    hash,
    cancelToken,
  }: UploadOptions) {
    const formData = new FormData();
    formData.append("chunk", chunk);
    formData.append("hash", hash);
    formData.append("index", index);
    await axios.post("http://localhost:3000/api/users", formData, {
      cancelToken,
    });
  }

  const uploaderConfig: Config = useMemo(
    () => ({
      chunkSize: 5 * 1024 * 1024, // 5MB
      concurrency: 5,
      maxRetries: 3,
      // startOffset: 6, // 從索引為10的切片位置開始傳
      // includeChunks:[1,6], // 只上傳索引為1和6的切片,只有startOffset為0或空時才生效
      uploadFunction,
      onProgress: (progress) => {
        setProgress(progress);
      },
      onSuccess: () => {
        console.log("上傳完畢");
      },
      onSpeed: (speed) => {
        setSpeed(speed);
      },
    }),
    []
  );

  const uploader = useMemo(
    () => createUploader(uploaderConfig),
    [uploaderConfig]
  );

  const handleFileChange = (event) => {
    const file = event.target.files[0];
    uploader?.upload(file);
  };

  const handlePause = () => {
    uploader?.pause();
  };

  const handleResume = () => {
    uploader?.resume();
  };

  return (
    <div>
      <input type="file" onChange={handleFileChange} />
      <button onClick={handlePause}>暫停上傳</button>
      <button onClick={handleResume}>繼續(xù)上傳</button>
      <div>上傳進度:{progress.toFixed(2)}%</div>
      <div>上傳速度:{speed}</div>
    </div>
  );
};

export default FileUpload;

這段代碼把文件上傳功能封裝成了 React Hook。Hook 里用useRef創(chuàng)建文件輸入框的引用,uploadFile函數(shù)處理文件上傳邏輯,最后返回fileInputRefuploadFile,方便在其他組件里復用文件上傳功能。

  1. 使用上面封裝好的 Hooks 示例
import { useState, useMemo, useCallback } from "react";
import createUploader from "enlarge-file-upload";
import type { Config, UploadOptions } from "enlarge-file-upload";
import axios from "axios";

const useFileUploader = () => {
  const [progress, setProgress] = useState(0);
  const [speed, setSpeed] = useState("0 MB/s");

  const uploadFunction = useCallback(
    async ({ chunk, index, hash, cancelToken }: UploadOptions) => {
      const formData = new FormData();
      formData.append("chunk", chunk);
      formData.append("hash", hash);
      formData.append("index", index);
      await axios.post("http://localhost:3000/api/users", formData, {
        cancelToken,
      });
    },
    []
  );

  const uploaderConfig: Config = useMemo(
    () => ({
      chunkSize: 5 * 1024 * 1024, // 5MB
      concurrency: 5,
      maxRetries: 3,
      // startOffset: 6, // 從索引為10的切片位置開始傳
      // includeChunks:[1,6], // 只上傳索引為1和6的切片,只有startOffset為0或空時才生效
      uploadFunction,
      onProgress: (progress) => {
        setProgress(progress);
      },
      onSuccess: () => {
        console.log("Upload complete");
      },
      onSpeed: (speed) => {
        setSpeed(speed);
      },
    }),
    [uploadFunction]
  );

  const uploader = useMemo(
    () => createUploader(uploaderConfig),
    [uploaderConfig]
  );

  const uploadFile = useCallback(
    (file) => {
      uploader?.upload(file);
    },
    [uploader]
  );

  const pauseUpload = useCallback(() => {
    uploader?.pause();
  }, [uploader]);

  const resumeUpload = useCallback(() => {
    uploader?.resume();
  }, [uploader]);

  return {
    progress,
    speed,
    uploadFile,
    pauseUpload,
    resumeUpload,
  };
};

export default useFileUploader;

這個示例里,引入封裝好的useFileUpload Hook,通過解構拿到fileInputRefuploadFile。在組件里用fileInputRef關聯(lián)文件輸入框,點按鈕就調(diào)用uploadFile函數(shù)上傳文件,在 React 項目里用起來就更方便了。

大文件上傳在前端開發(fā)里很重要,搞懂原理和實現(xiàn)方法,再用好工具,就能給用戶更好的上傳體驗。希望這篇文章能幫大家深入了解前端大文件上傳,在項目開發(fā)里用得得心應手。


作者:小螞蟻i
鏈接:https://juejin.cn/post/7474923858165137417
來源:稀土掘金
著作權歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權,非商業(yè)轉(zhuǎn)載請注明出處。

該文章在 2025/4/1 12:54:00 編輯過
關鍵字查詢
相關文章
正在查詢...
點晴ERP是一款針對中小制造業(yè)的專業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國內(nèi)大量中小企業(yè)的青睞。
點晴PMS碼頭管理系統(tǒng)主要針對港口碼頭集裝箱與散貨日常運作、調(diào)度、堆場、車隊、財務費用、相關報表等業(yè)務管理,結合碼頭的業(yè)務特點,圍繞調(diào)度、堆場作業(yè)而開發(fā)的。集技術的先進性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點晴WMS倉儲管理系統(tǒng)提供了貨物產(chǎn)品管理,銷售管理,采購管理,倉儲管理,倉庫管理,保質(zhì)期管理,貨位管理,庫位管理,生產(chǎn)管理,WMS管理系統(tǒng),標簽打印,條形碼,二維碼管理,批號管理軟件。
點晴免費OA是一款軟件和通用服務都免費,不限功能、不限時間、不限用戶的免費OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved