最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

使用Vue進(jìn)行圖片壓縮的實(shí)現(xiàn)方案和對(duì)比

 更新時(shí)間:2025年10月23日 09:47:35   作者:涼柚ˇ  
在 Vue 項(xiàng)目中處理用戶上傳的大圖片時(shí),通過(guò)前端壓縮減小圖片體積是優(yōu)化上傳體驗(yàn)的有效方式,本文將和大家介紹幾個(gè)具體實(shí)現(xiàn)方案及相關(guān)說(shuō)明,希望對(duì)大家有所幫助

在 Vue 項(xiàng)目中處理用戶上傳的大圖片時(shí),通過(guò)前端壓縮減小圖片體積是優(yōu)化上傳體驗(yàn)的有效方式。以下為具體實(shí)現(xiàn)方案及相關(guān)說(shuō)明:

一、圖片壓縮方案對(duì)比

不同壓縮方案在體積縮減、兼容性、耗時(shí)等方面各有特點(diǎn),具體如下:

方案體積縮減兼容性耗時(shí)備注
Canvas 縮放60-85%99%本文主方案
WebP encode額外-30%92%需服務(wù)端配合回退 JPG
WebAssembly70-90%92%mozJPEG/avif-js,包大
服務(wù)端壓縮0%100%前端仍要先傳原圖

二、核心實(shí)現(xiàn):Canvas 縮放壓縮

利用 HTML5 的 Canvas API,通過(guò)調(diào)整圖片尺寸和質(zhì)量實(shí)現(xiàn)壓縮,是兼容性和效果平衡較好的方案。

1. 壓縮工具函數(shù)

核心思路是利用 HTML5 的 Canvas API 對(duì)圖片進(jìn)行壓縮,主要通過(guò)調(diào)整圖片尺寸和質(zhì)量來(lái)實(shí)現(xiàn)。

/**
 * 圖片壓縮工具
 * @param file 原始圖片文件
 * @param options 壓縮選項(xiàng)
 * @returns 壓縮后的圖片文件
 */
export const compressImage = async (
  file: File,
  options: {
    maxWidth?: number;    // 最大寬度
    maxHeight?: number;   // 最大高度
    quality?: number;     // 圖片質(zhì)量 0-1
  } = {}
): Promise<File | null> => {
  // 默認(rèn)配置
  const {
    maxWidth = 1200,
    maxHeight = 1200,
    quality = 0.8
  } = options;

  return new Promise((resolve) => {
    // 創(chuàng)建圖片對(duì)象
    const img = new Image();
    const objectUrl = URL.createObjectURL(file);
    img.src = objectUrl;

    img.onload = () => {
      URL.revokeObjectURL(objectUrl);

      // 計(jì)算壓縮后的尺寸(保持比例)
      let width = img.width;
      let height = img.height;

      // 如果圖片尺寸超過(guò)最大限制,按比例縮小
      if (width > maxWidth || height > maxHeight) {
        const ratio = Math.min(maxWidth / width, maxHeight / height);
        width = width * ratio;
        height = height * ratio;
      }

      // 創(chuàng)建Canvas元素
      const canvas = document.createElement('canvas');
      canvas.width = width;
      canvas.height = height;

      // 繪制圖片到Canvas
      const ctx = canvas.getContext('2d');
      if (!ctx) {
        resolve(null);
        return;
      }
      
      ctx.drawImage(img, 0, 0, width, height);

      // 將Canvas內(nèi)容轉(zhuǎn)換為Blob
      canvas.toBlob(
        (blob) => {
          if (!blob) {
            resolve(null);
            return;
          }

          // 轉(zhuǎn)換為File對(duì)象
          const compressedFile = new File(
            [blob],
            file.name,
            { type: blob.type, lastModified: Date.now() }
          );
          resolve(compressedFile);
        },
        file.type || 'image/jpeg',
        quality
      );
    };

    img.onerror = () => {
      URL.revokeObjectURL(objectUrl);
      resolve(null);
    };
  });
};

2. Vue3 組件中使用示例

<template>
  <div class="image-upload">
    <input
      type="file"
      accept="image/*"
      @change="handleFileChange"
      class="file-input"
    />
    
    <div v-if="previewUrl" class="preview">
      <img :src="previewUrl" alt="預(yù)覽圖" class="preview-img" />
      <p>原始大小: {{ originalSize }}KB</p>
      <p v-if="compressedSize">壓縮后大小: {{ compressedSize }}KB</p>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import { compressImage } from '@/utils/imageCompressor';

const previewUrl = ref('');
const originalSize = ref(0);
const compressedSize = ref(0);

const handleFileChange = async (e: Event) => {
  const input = e.target as HTMLInputElement;
  if (!input.files || input.files.length === 0) return;

  const file = input.files[0];
  
  // 顯示原始文件大小
  originalSize.value = Math.round(file.size / 1024);
  
  // 如果文件小于500KB,不壓縮直接使用
  if (file.size < 500 * 1024) {
    previewUrl.value = URL.createObjectURL(file);
    compressedSize.value = originalSize.value;
    return;
  }

  // 壓縮圖片
  const compressedFile = await compressImage(file, {
    maxWidth: 1000,
    maxHeight: 1000,
    quality: 0.7
  });

  if (compressedFile) {
    previewUrl.value = URL.createObjectURL(compressedFile);
    compressedSize.value = Math.round(compressedFile.size / 1024);
    
    // 這里可以將compressedFile上傳到服務(wù)器
    // await uploadToServer(compressedFile);
  }
};
</script>

<style scoped>
.image-upload {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.file-input {
  padding: 0.5rem;
  border: 1px solid #ccc;
  border-radius: 4px;
}

.preview {
  margin-top: 1rem;
}

.preview-img {
  max-width: 100%;
  border-radius: 4px;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
</style>

三、服務(wù)端二次校驗(yàn)(Node 示例)

router.post('/upload', multer().single('file'), async (req, res) => {
  const { buffer, mimetype, size } = req.file;
  if (size > 1024 * 1024) return res.status(413).send('too big');
  if (!['image/jpeg', 'image/webp'].includes(mimetype)) return res.status(400).send('bad type');

  // 計(jì)算 SSIM 或 Magic Number 防止“偽造壓縮”
  const metadata = await sharp(buffer).metadata();
  if (metadata.width! > 1600) return res.status(400).send('width overflow');

  // 真正落盤(pán)
  await putToOSS(buffer, mimetype);
  res.json({ url });
});

四、注意事項(xiàng)

壓縮會(huì)損失一定畫(huà)質(zhì),需根據(jù)業(yè)務(wù)場(chǎng)景平衡畫(huà)質(zhì)與文件大小;

對(duì)于幾十 MB 的超大圖片,可考慮分階段壓縮(先大幅縮小尺寸,再調(diào)整質(zhì)量);

服務(wù)端必須進(jìn)行二次校驗(yàn),防止前端繞過(guò)壓縮邏輯上傳超大文件。

到此這篇關(guān)于使用Vue進(jìn)行圖片壓縮的實(shí)現(xiàn)方案和對(duì)比的文章就介紹到這了,更多相關(guān)Vue圖片壓縮內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Vue組件中的data必須是一個(gè)function的原因淺析

    Vue組件中的data必須是一個(gè)function的原因淺析

    這篇文章主要介紹了Vue組件中的data必須是一個(gè)function的原因淺析,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2018-09-09
  • vue3.0 CLI - 2.4 - 新組件 Forms.vue 中學(xué)習(xí)表單

    vue3.0 CLI - 2.4 - 新組件 Forms.vue 中學(xué)習(xí)表單

    這篇文章主要介紹了vue3.0 CLI - 2.4 - 新組件 Forms.vue 中學(xué)習(xí)表單的相關(guān)知識(shí),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值 ,需要的朋友可以參考下
    2018-09-09
  • vue3使用全局websocket的示例詳解

    vue3使用全局websocket的示例詳解

    這篇文章主要為大家詳細(xì)介紹了vue3使用全局websocket的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),對(duì)我們深入學(xué)習(xí)vue3有一定的幫助,感興趣的小伙伴可以參考一下
    2023-10-10
  • vue初嘗試--項(xiàng)目結(jié)構(gòu)(推薦)

    vue初嘗試--項(xiàng)目結(jié)構(gòu)(推薦)

    這篇文章主要介紹了vue初嘗試--項(xiàng)目結(jié)構(gòu)的相關(guān)知識(shí),需要的朋友可以參考下
    2018-01-01
  • vue金額格式化保留兩位小數(shù)的實(shí)現(xiàn)

    vue金額格式化保留兩位小數(shù)的實(shí)現(xiàn)

    這篇文章主要介紹了vue金額格式化保留兩位小數(shù)的實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-04-04
  • 基于vue實(shí)現(xiàn)頁(yè)面滾動(dòng)加載的示例詳解

    基于vue實(shí)現(xiàn)頁(yè)面滾動(dòng)加載的示例詳解

    頁(yè)面內(nèi)容太多會(huì)導(dǎo)致加載速度過(guò)慢,這時(shí)可考慮使用滾動(dòng)加載即還沒(méi)有出現(xiàn)在可視范圍內(nèi)的內(nèi)容塊先不加載,出現(xiàn)后再加載,所以本文給大家介紹了基于vue實(shí)現(xiàn)頁(yè)面滾動(dòng)加載的示例,需要的朋友可以參考下
    2024-01-01
  • vue?element-ui動(dòng)態(tài)橫向統(tǒng)計(jì)表格的實(shí)現(xiàn)

    vue?element-ui動(dòng)態(tài)橫向統(tǒng)計(jì)表格的實(shí)現(xiàn)

    這篇文章主要介紹了vue?element-ui動(dòng)態(tài)橫向統(tǒng)計(jì)表格的實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • vue打包(hash和history)部署詳細(xì)步驟

    vue打包(hash和history)部署詳細(xì)步驟

    這篇文章主要介紹了vue打包(hash和history)部署詳細(xì)步驟,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • elementUI動(dòng)態(tài)表單?+?el-select?按要求禁用問(wèn)題

    elementUI動(dòng)態(tài)表單?+?el-select?按要求禁用問(wèn)題

    這篇文章主要介紹了elementUI動(dòng)態(tài)表單?+?el-select?按要求禁用問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • vue中數(shù)組加Key方式

    vue中數(shù)組加Key方式

    這篇文章主要介紹了vue中數(shù)組加Key方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-03-03

最新評(píng)論

洛南县| 收藏| 彭阳县| 阳原县| 滨州市| 育儿| 自贡市| 仙居县| 周宁县| 孝感市| 马边| 卢龙县| 凤阳县| 丰都县| 黄大仙区| 长泰县| 湖州市| 伊川县| 绥棱县| 昆山市| 临泽县| 莎车县| 墨竹工卡县| 鸡泽县| 呼图壁县| 南开区| 拉孜县| 乐至县| 仲巴县| 安阳县| 阿克苏市| 那曲县| 噶尔县| 将乐县| 芜湖市| 务川| 鲁山县| 博乐市| 康平县| 阳江市| 拉萨市|