node.js 实战——在express 中将input file 美化,并完成裁剪、上传进度条

发布于:2025-05-09 ⋅ 阅读:(14) ⋅ 点赞:(0)

美化上传按钮

在这里插入图片描述

在ejs 页面

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"></meta>
    <title><%= title %></title>
    <link rel='stylesheet' href='/stylesheets/form.css'/>
    <!-- 本地 Bootstrap 引入方式 -->
    <link href="/bootstrap/css/bootstrap.min.css" rel="stylesheet">
    <script src="/bootstrap/js/bootstrap.bundle.min.js"></script>
    <script src="./javascripts/image-upload.js"></script>
</head>
<body>
<div class="container">
    <h1>文件上传</h1>
    <from action="/upload-img" method="post" enctype="multipart/form-data">
        <label class="upload-container">
            <span class="upload-icon" id="uploadIcon">+</span>
            <input accept="image/*" id="avatarInput" type="file" />
            <img id="avatarPreview" class="preview-img d-done" />
            <button type="button" class="remove-btn" id="removeBtn">x</button>
        </label>


        <button type="submit" class="btn btn-primary mt-3">提交</button>
    </from>
</div>
</body>
</html>

样式

.upload-container{
   width: 150px;
  height: 150px;
  border: 2px solid #ccc;
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  background-color: #f8f9fa;
  transition:border-color 0.3s;

  .upload-icon{
    font-size:2rem;
    color:#999;
    //禁用鼠标事件,该元素变得“不可点击”、“鼠标穿透”
    pointer-events: none;  //用来控制一个元素是否能响应鼠标事件(点击、悬停、拖动等)

  }

  .preview-img{
    width:100%;
    height: 100%;
    object-fit: cover;
    position: absolute;
    top: 0;
    left: 0;
  }

  .remove-btn{
    position: absolute;
    top:5px;
    right:5px;
    background-color:rgba(0,0,0,.6);
    color:#ffffff;
    border:none;
    border-radius:50%;
    width:24px;
    height:24px;
    display:none;
    align-items: center;
    justify-content: center;
    cursor:pointer;
    font-weight: bold;
  }
}

.upload-container:hover{
  border-color: #007bff;
}

.upload-container input[type="file"]{
  position: absolute;
  opacity: 0;
  height: 100%;
  width: 100%;
  cursor: pointer;
}



完成效果

这个效果没有裁剪,进度条、多图片上传
在这里插入图片描述

上传进度条

   <div class="progress mt-2 d-done" id="progressWrapper">
            <div class="progress-bar" role="progressbar" id="uploadProgress" style="width: 0%">0%</div>

        </div>
        
 document.getElementById('uploadForm').addEventListener('submit', function(e){

        e.preventDefault();
        // const blob =preview._blob;
        // if(!blob){
        //     alert("请先选择并裁剪头像");
        //     return;
        // }

        const file =input.files[0];
        if(!file) return alert('Please upload a valid image!');

        let formData = new FormData();
        formData.append('file', file);

        let xhr = new XMLHttpRequest();
        xhr.open('POST', '/upload-avatar');

        xhr.upload.addEventListener('progress', (e) => {
            if(e.lengthComputable){
                let percent = Math.round((e.loaded / e.total) * 100);
                progressWrapper.classList.remove('d-none');
                progressBar.style.width= percent + '%';
                progressBar.innerText = percent + '%';
            }
        })


        xhr.onload =function () {
            if(xhr.status === 200) {
                alert("successfully uploaded!");
            }else{
                alert("fail to upload");
            }
        }
        xhr.send(formData);

    })


使用cropperjs 裁剪图片

使用npm安装

npm install cropperjs@1.5.13

❗ 关键点:cropperjs@2.x 为模块化版本,不再提供 dist/ 下的浏览器用 JS/CSS 文件

从 v2.0.0 开始,cropperjs 改为 纯 ESM(ES Module)包,它不再包含:

  • cropper.js
  • cropper.css
  • dist/ 文件夹

📌 小提示

版本 适合人群 是否自带 dist/
1.5.13 普通浏览器/EJS 项目 ✅ 有 JS/CSS,推荐
2.x Vite/Webpack 打包项目 ❌ 无,需构建

引入js、css

   <!--本地开发引入 cropper -->
    <link rel="stylesheet" href="/cropper/cropper.css">
    <script src="/cropper/cropper.js"></script>

弹框

<!-- 裁剪模态框-->
    <div class="modal fade modal-mask" id="cropModal" tabindex="1" aria-hidden="true">
        <div class="modal-dialog modal-dialog-centered modal-fullscreen">
            <div class="modal-content p-3">
                <div class="modal-body" style="width: 100%; height: 600px;">
                    <img id="cropImg"  />
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
                    <button type="button" class="btn btn-success" id="cropConfirm">确认裁剪</button>
                </div>
            </div>
        </div>

    </div>

js

input.addEventListener('change', (e)=> {
        let that=e.target;

        let file=that.files[0];
        if(file && file.type.startsWith('image/')) {
            let reader=new FileReader();
            reader.onloadend = (e) => {

                //未裁剪前使用的代码
                // preview.src = e.target.result;
                // preview.classList.remove('d-none');
                // removeBtn.style.display = 'flex';
                // uploadIcon.style.display = 'none';

                //裁剪时的代码
                cropImage.src = e.target.result;
                new bootstrap.Modal(document.getElementById('cropModal')).show();

                cropImage.onload =()=>{
                    if(cropper) cropper.destroy();
                    cropper =new Cropper(cropImage,{
                        aspectRatio: 1,
                        autoCropArea:1,
                        viewMode:2
                    })
                }



            }
            reader.readAsDataURL(file);
        }
    })

在这里插入图片描述


网站公告

今日签到

点亮在社区的每一天
去签到