图片粘贴上传实现

图片上传 html demo

直接粘贴本地运行查看效果即可,有看不懂的直接喂给 deepseek 会解释的很清晰

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>粘贴图片上传示例 - 使用场景,粘贴桌面图片上传、粘贴word 文档中图片上传、直接截图上传等</title>
  <style>
    body {
      font-family: Arial, sans-serif;
      padding: 20px;
    }
    .upload-area {
      width: 100%;
      height: 200px;
      border: 2px dashed #ccc;
      display: flex;
      align-items: center;
      justify-content: center;
      color: #666;
      font-size: 18px;
      margin-bottom: 20px;
    }
    .file-list {
      margin-top: 20px;
    }
    .file-item {
      margin-bottom: 10px;
      padding: 10px;
      border: 1px solid #ddd;
      background-color: #f9f9f9;
    }
    .file-item.uploading {
      background-color: #e0f7fa;
    }
    .file-item.done {
      background-color: #e8f5e9;
    }
    .file-item.error {
      background-color: #ffebee;
    }
  </style>
</head>
<body>
  <h1>粘贴图片上传示例</h1>
  <div class="upload-area">
    请在此区域粘贴图片
  </div>
  <div class="file-list">
    <h2>文件列表</h2>
    <div id="file-list-container"></div>
  </div>

  <script>
    // 模拟语言包
    const t = (key) => {
      const translations = {
        'examination.pasteNoContent': '粘贴内容为空',
      };
      return translations[key] || key;
    };

    // 生成唯一 ID
    const uuidv4 = () => {
      return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
        const r = (Math.random() * 16) | 0;
        const v = c === 'x' ? r : (r & 0x3) | 0x8;
        return v.toString(16);
      });
    };

    // 文件上传前的校验
    const onBeforeUpload = async (file, { maxHeight, maxWidth, size, maxCount, t, fileList }) => {
      if (fileList.length >= maxCount) {
        alert(`最多只能上传 ${maxCount} 张图片`);
        return false;
      }
      if (file.size > size) {
        alert(`文件大小不能超过 ${size / 1024 / 1024}MB`);
        return false;
      }
      return true;
    };

    // 模拟文件上传函数
    const fileUpload = (file, { onSuccess, onError }) => {
      setTimeout(() => {
        if (Math.random() > 0.5) {
          onSuccess({ url: 'https://example.com/uploaded-image.jpg' });
        } else {
          onError('上传失败,请重试');
        }
      }, 2000); // 模拟 2 秒上传时间
    };

    // 数据处理函数
    const dataHandle = ({ file, fileList }) => {
      return { file, fileList };
    };

    // 粘贴图片上传处理函数
    const handelPasteImageUpload = async (event, {
      t,
      resource = { images: [] },
      onStartUpload,
      onUploadSuccess,
      onUploadError,
      imageUploadLimitConfig,
    }) => {
      const fileList = resource.images || [];
      const clipboardData = event.clipboardData;
      if (clipboardData) {
        const items = clipboardData.items || [];
        if (items.length <= 0) {
          alert(t('examination.pasteNoContent'));
          return;
        }
        for (let i = 0; i < items.length; i++) {
          const item = items[i];
          if (item.type.indexOf('image') !== -1) {
            event.preventDefault(); // 阻止默认行为
            const originFileObj = item.getAsFile(); // 获取文件对象

            // 构建文件数据对象
            const fileDataObj = {
              originFileObj,
              uid: uuidv4(),
              lastModified: originFileObj.lastModified,
              name: originFileObj.name,
              size: originFileObj.size,
              type: originFileObj.type,
            };

            const { maxHeight, maxWidth, size, maxCount } = imageUploadLimitConfig;

            // 文件上传前的校验
            const flag = await onBeforeUpload(originFileObj, {
              maxHeight,
              maxWidth,
              size: size.image,
              maxCount: maxCount.image,
              t,
              fileList,
            });

            if (flag) {
              const newFileList = [...fileList, fileDataObj].map((item) => {
                if (item.uid === fileDataObj.uid) {
                  return { ...item, status: 'uploading' };
                }
                return item;
              });

              // 调用开始上传回调
              onStartUpload(dataHandle({ file: fileDataObj, fileList: newFileList }));

              // 模拟文件上传
              fileUpload(originFileObj, {
                onSuccess: (response) => {
                  const updatedFileList = newFileList.map((item) => {
                    if (item.uid === fileDataObj.uid) {
                      return { ...item, status: 'done', response };
                    }
                    return item;
                  });
                  onUploadSuccess(dataHandle({ file: fileDataObj, fileList: updatedFileList }));
                },
                onError: (error) => {
                  const updatedFileList = newFileList.map((item) => {
                    if (item.uid === fileDataObj.uid) {
                      return { ...item, status: 'error', response: error };
                    }
                    return item;
                  });
                  onUploadError(dataHandle({ file: fileDataObj, fileList: updatedFileList }));
                },
              });
            }
          }
        }
      }
    };

    // 初始化
    document.addEventListener('paste', (event) => {
      handelPasteImageUpload(event, {
        t,
        resource: { images: [] },
        onStartUpload: (data) => {
          console.log('开始上传:', data);
          renderFileList(data.fileList);
        },
        onUploadSuccess: (data) => {
          console.log('上传成功:', data);
          renderFileList(data.fileList);
        },
        onUploadError: (data) => {
          console.error('上传失败:', data);
          renderFileList(data.fileList);
        },
        imageUploadLimitConfig: {
          maxHeight: 1000,
          maxWidth: 1000,
          size: { image: 5 * 1024 * 1024 }, // 5MB
          maxCount: { image: 10 },
        },
      });
    });

    // 渲染文件列表
    const renderFileList = (fileList) => {
      const container = document.getElementById('file-list-container');
      container.innerHTML = fileList
        .map(
          (file) => `
          <div class="file-item ${file.status}">
            <strong>${file.name}</strong> - ${file.status}
            ${file.response ? `<br>响应: ${JSON.stringify(file.response)}` : ''}
          </div>
        `
        )
        .join('');
    };
  </script>
</body>
</html>
相关推荐
无羡仙3 分钟前
替代 Object.freeze 的精准只读模式
前端·javascript
小菜全1 小时前
uniapp新增页面及跳转配置方法
开发语言·前端·javascript·vue.js·前端框架
白水清风1 小时前
关于Js和Ts中类(class)的知识
前端·javascript·面试
前端Hardy1 小时前
只用2行CSS实现响应式布局,比媒体查询更优雅的布局方案
javascript·css·html
车口1 小时前
滚动加载更多内容的通用解决方案
javascript
艾小码2 小时前
手把手教你实现一个EventEmitter,彻底告别复杂事件管理!
前端·javascript·node.js
心一信息3 小时前
ThreeJS骨骼示例
css·css3·html5
Jedi Hongbin4 小时前
Three.js shader内置矩阵注入
前端·javascript·three.js
掘金安东尼5 小时前
Node.js 如何在 2025 年挤压 I/O 性能
前端·javascript·github
得物技术5 小时前
前端日志回捞系统的性能优化实践|得物技术
前端·javascript·性能优化