zhuangzhuangzhuangsh 2025-01-15 15:57 采纳率: 50%
浏览 45
已结题

wangeditor超过1m的图片上传前压缩照片

wangeditor超过1m的图片上传前压缩照片,要怎么实现?一直搞不来


<template>
  <div class="container">
    <Toolbar
        style="border: 1px solid #ccc; width: 1180px;"
        :editor="editorRef"
        :default-config="toolbarConfig"
        :mode="mode"
    />
    <Editor
        style="height: 500px; width: 1180px; overflow-y: hidden; border: 1px solid #ccc;"
        v-model="valueHtml"
        :default-config="editorConfig"
        :mode="mode"
        @on-created="handleCreated"
    />
  </div>
</template>

<script setup lang="ts">
import '@wangeditor/editor/dist/css/style.css';
import {onBeforeUnmount, ref, shallowRef, watch} from 'vue';
import type {IEditorConfig, IToolbarConfig} from '@wangeditor/editor'; // 使用 type 导入
import {Editor, Toolbar} from '@wangeditor/editor-for-vue';
import {ElMessage} from "element-plus";

const props = defineProps<{
  modelValue: string;
  mode?: string;
}>();

const emits = defineEmits<{
  (e: 'update:modelValue', value: string): void;
}>();

const editorRef = shallowRef();
const valueHtml = ref<string>(props.modelValue || '');

watch(valueHtml, (newHtml) => {
  emits('update:modelValue', newHtml);
});

const toolbarConfig: Partial<IToolbarConfig> = {
  insertKeys: {
    index: 0,
    keys: ['uploadAttachment'],
  },
};

const editorConfig: Partial<IEditorConfig> = {
  hoverbarKeys: {
    attachment: {
      menuKeys: ['downloadAttachment'],
    },
  },

  placeholder: '请输入内容...',
  MENU_CONF: {

    uploadImage: {
      server: `${import.meta.env.VITE_API_BASE_URL}/Articles/uploadFile`,
      fieldName: 'file',
      maxFileSize: 20000 * 1024,
      base64LimitSize: 5 * 1024 ,
      withCredentials: true,
      maxNumberOfFiles: 10,
      methods: 'post',
      metaWithUrl: true,

      onBeforeUpload(file:File) {

        console.log('文件对象:', JSON.stringify(file, null, 2)); // 输出文件对象的完整结构

        // 获取第一个键
        const key = Object.keys(file)[0];

        // 通过键访问文件数据
        const fileData = file[key];
        console.log('文件数据:', fileData);
        const fileName = fileData.name;

        const fileSizeMB = (fileData.size / 1024 / 1024).toFixed(2);
        console.log('文件名:', fileName);
        console.log('文件大小:', fileSizeMB + 'MB');
        console.log('文件类型:', fileData.type);

        if (fileData.size / 1024 / 1024 > 1) {
          console.log('文件超过1MB,开始压缩...');

          console.log('fileData.data 属性:', Object.keys(fileData.data));
          console.log('fileData.data.size:', fileData.data.size);
          console.log('fileData.data.type:', fileData.data.type);
          console.log('fileData.data.slice:', fileData.data.slice);

          return new Promise((resolve, reject) => {
            // 确保 fileData.data 是一个有效的 Blob 或 File 对象
            if (!(fileData.data instanceof Blob)) {
              reject(new Error('fileData.data 不是一个有效的 Blob 对象'));
              return;
            }

            const reader = new FileReader();
            reader.onload = function (event) {
              const img = new Image();
              img.onload = function () {
                const canvas = document.createElement('canvas');
                const ctx = canvas.getContext('2d');

                // 设置压缩后的宽度和高度
                const MAX_WIDTH = 800;
                const MAX_HEIGHT = 800;
                let width = img.width;
                let height = img.height;

                if (width > height) {
                  if (width > MAX_WIDTH) {
                    height *= MAX_WIDTH / width;
                    width = MAX_WIDTH;
                  }
                } else {
                  if (height > MAX_HEIGHT) {
                    width *= MAX_HEIGHT / height;
                    height = MAX_HEIGHT;
                  }
                }

                canvas.width = width;
                canvas.height = height;

                // 绘制图像到 canvas
                ctx.drawImage(img, 0, 0, width, height);

                // 将 canvas 转换为 Blob
                canvas.toBlob((blob) => {
                  if (!blob) {
                    reject(new Error('压缩失败'));
                    return;
                  }

                  // 创建一个新的 File 对象
                  const compressedFile = new File([blob], fileName, {
                    type: fileData.type,
                    lastModified: Date.now(),
                  });

                  // 返回与原始 fileData 格式相同的对象
                  const compressedFileData = {
                    ...fileData,
                    size: blob.size,
                    data: blob,
                  };

                  console.log('压缩后的文件大小:', (blob.size / 1024 / 1024).toFixed(2) + 'MB');
                  resolve(compressedFileData);
                }, fileData.type, 0.7); // 0.7 是压缩质量,可以根据需要调整
              };
              img.src = event.target.result;
            };
            reader.onerror = reject;
            reader.readAsDataURL(fileData); // 直接使用 fileData 作为 File 对象
          });
        } else {
          console.log('文件大小小于或等于1MB,直接上传...');
          return file;
        }
        },
      onProgress(progress: number) {
        console.log('上传进度:', progress);
      },
      onSuccess(file: File, res: any) {
        console.log('上传成功:', file, res);
        ElMessage.success('图片上传成功');
      },
      onFail(file: File, res: any) {
        console.log('上传失败:', file, res);
        ElMessage.error('图片上传失败');
      },
      onFinished(files: File[], res: any) {
        console.log('所有文件上传完成:', files, res);
      },
      onFinishedFail(files: File[], res: any) {
        console.log('文件上传失败:', files, res);
      },
      customInsert(res: any, insertFn: Function) {
        // console.log('自定义插入:', res);
        insertFn(res.data);
      },
      // 自定义插入图片
    },
    uploadVideo: {
      server: `${import.meta.env.VITE_API_BASE_URL}/Articles/uploadFile`,
      fieldName: 'file',
      maxFileSize: 1000000 * 1024,
      withCredentials: true,
      maxNumberOfFiles: 10,
      methods: 'post',
      metaWithUrl: true,
      onProgress(progress: number) {},
      onSuccess(file: File, res: any) {},
      onFail(file: File, res: any) {},
      onFinished(files: File[], res: any) {},
      onFinishedFail(files: File[], res: any) {},
      customInsert(res: any, insertFn: Function) {
        insertFn(res.data);
      },
    },
    uploadAttachment: {
      server: `${import.meta.env.VITE_API_BASE_URL}/Articles/uploadFile`,
      fieldName: 'file',
      maxFileSize: 1000000 * 1024,
      withCredentials: true,
      maxNumberOfFiles: 10,
      methods: 'post',
      metaWithUrl: true,
      onProgress(progress: number) {},
      onSuccess(file: File, res: any) {},
      onFail(file: File, res: any) {},
      onFinished(files: File[], res: any) {},
      onFinishedFail(files: File[], res: any) {},
      customInsert(res: any, file: File, insertFn: Function) {
        insertFn(file.name, res.data);
      },
    },
  },
};


onBeforeUnmount(() => {
  const editor = editorRef.value;
  if (editor) editor.destroy();
});

const handleCreated = (editorInstance: any) => {
  editorRef.value = editorInstance;
};
</script>

<style scoped>
.container {
  z-index: 2;
  background: #fff;
  float: left;
  width: 1200px;
  height: 100%;
}
</style>

  • 写回答

3条回答 默认 最新

  • asmlcat 2025-01-16 11:24
    关注

    有一个customBrowseAndUpload完全定制上传逻辑就行了吧

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

问题事件

  • 系统已结题 1月25日
  • 已采纳回答 1月17日
  • 创建了问题 1月15日