原生html+js+css+php多图上传带预览可增删判断图片大小和后缀

原生html+js+css+php多图上传带预览可增删,前后端判断图片大小和后缀

源码来自AI,有改动,整合亲测可用

<?php
// 设置允许的最大文件大小为 2MB
$maxFileSize = 2 * 1024 * 1024;
$allowedExtensions = ['jpg', 'jpeg', 'png', 'gif'];// 上传目录(请确保目录存在并具备写入权限)
$uploadDir = __DIR__ . '/uploads/';$response = ['success' => false,'url' => '','error' => ''
];if (isset($_GET['act']) && $_GET['act'] === 'up') {
if (isset($_FILES['file']) && $_FILES['file']['error'] === UPLOAD_ERR_OK) {if (!is_dir($uploadDir)) {  @mkdir($uploadDir, 0755, true); }$file = $_FILES['file'];// 检查文件大小if ($file['size'] > $maxFileSize) {$response['error'] = '文件大小不能超过 2MB';echo json_encode($response);exit;}// 检查文件扩展名$fileExtension = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));if (!in_array($fileExtension, $allowedExtensions)) {$response['error'] = '仅支持 jpg, jpeg, png, gif 格式';echo json_encode($response);exit;}// 为文件生成唯一名称$newFileName = uniqid('img_', true) . '.' . $fileExtension;$targetFilePath = $uploadDir . $newFileName;// 移动上传文件到目标目录if (move_uploaded_file($file['tmp_name'], $targetFilePath)) {$response['success'] = true;$response['url'] = '/uploads/' . $newFileName;  // 根据实际路径配置返回 URL} else {$response['error'] = '文件上传失败,请重试';}} else {$response['error'] = '上传文件不存在或上传出错';}
header('Content-Type: application/json');
echo json_encode($response);
exit();}
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>多图片上传带进度条</title><style>* {box-sizing: border-box;}body {font-family: Arial, sans-serif;padding: 20px;}.form-container {max-width: 600px;margin: auto;background-color: #fff;padding: 20px;border-radius: 8px;box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);}.form-group {margin-bottom: 15px;}.form-group label {display: block;font-weight: bold;margin-bottom: 5px;}.form-group input[type="text"] {width: 100%;padding: 10px;border: 1px solid #ddd;border-radius: 4px;}.upload-container {display: flex;flex-wrap: wrap;gap: 10px;margin-top: 10px;}.image-preview {position: relative;width: 120px;height: 120px;border: 2px solid #ddd;border-radius: 4px;overflow: hidden;background-color: #f5f5f5;display: flex;align-items: center;justify-content: center;}.image-preview img {width: 100%;height: 100%;object-fit: cover;}.delete-btn {position: absolute;top: 5px;right: 5px;background-color: rgba(255, 0, 0, 0.7);color: #fff;border: none;border-radius: 50%;cursor: pointer;width: 20px;height: 20px;display: flex;align-items: center;justify-content: center;}.progress-bar {width: 100%;background-color: #f3f3f3;height: 10px;border-radius: 5px;overflow: hidden;margin-top: 5px;display: none;}.progress-fill {height: 100%;background-color: #0073e6;width: 0;transition: width 0.2s;}.hidden-textarea {width: 100%;height: 80px;margin-top: 10px;display: none;}.upload-btn {display: flex;align-items: center;justify-content: center;width: 120px;height: 120px;border: 2px dashed #0073e6;border-radius: 4px;cursor: pointer;color: #0073e6;font-size: 1em;background-color: #f9f9f9;}.upload-btn input {display: none;}.btn-submit {width: 100%;padding: 10px;font-size: 1.1em;background-color: #0073e6;color: #fff;border: none;border-radius: 4px;cursor: pointer;margin-top: 20px;}</style>
</head>
<body><div class="form-container"><h2>招聘信息图片上传</h2><!-- 标题输入框 --><div class="form-group"><label for="title">标题</label><input type="text" id="title" placeholder="请输入图片标题"></div><!-- 图片上传容器 --><div class="upload-container" id="upload-container"><div class="upload-btn" onclick="document.getElementById('image-upload-input').click();">+ 上传图片<input type="file" id="image-upload-input" accept="image/*" onchange="prepareImageForUpload(event)"></div></div><!-- 已上传图片路径和显示上传图片的URL --><textarea id="uploaded-images-path" class="hidden-textarea" readonly></textarea><textarea id="uploaded-images-url" class="hidden-textarea" placeholder="已传图" readonly></textarea><!-- 提交按钮 --><button class="btn-submit" onclick="uploadAllImages()">提交上传</button>
</div><script>const MAX_IMAGES = 5; // 最大上传图片数量const MAX_FILE_SIZE = 2 * 1024 * 1024; // 文件大小限制为2MBconst allowedExtensions = ['jpg', 'jpeg', 'png', 'gif']; // 允许的文件格式const imagesToUpload = []; // 存储图片文件对象// 选择图片准备上传function prepareImageForUpload(event) {const file = event.target.files[0];if (!file) return;// 检查文件大小if (file.size > MAX_FILE_SIZE) {alert("文件大小不能超过2MB");return;}// 检查文件格式const fileExtension = file.name.split('.').pop().toLowerCase();if (!allowedExtensions.includes(fileExtension)) {alert("仅支持jpg, jpeg, png, gif格式");return;}imagesToUpload.push(file);displayImagePreview(file);// 更新上传按钮显示if (imagesToUpload.length >= MAX_IMAGES) {document.querySelector('.upload-btn').style.display = 'none';}}// 显示图片预览function displayImagePreview(file) {const reader = new FileReader();reader.onload = function(e) {const uploadContainer = document.getElementById('upload-container');const imagePreview = document.createElement('div');imagePreview.className = 'image-preview';const img = document.createElement('img');img.src = e.target.result;imagePreview.appendChild(img);const deleteBtn = document.createElement('button');deleteBtn.className = 'delete-btn';deleteBtn.innerText = '×';deleteBtn.onclick = () => removeImage(imagePreview, file);imagePreview.appendChild(deleteBtn);const progressBar = document.createElement('div');progressBar.className = 'progress-bar';const progressFill = document.createElement('div');progressFill.className = 'progress-fill';progressBar.appendChild(progressFill);imagePreview.appendChild(progressBar);uploadContainer.insertBefore(imagePreview, uploadContainer.lastElementChild);};reader.readAsDataURL(file);}// 删除图片function removeImage(imageElement, file) {imageElement.remove();const index = imagesToUpload.indexOf(file);if (index > -1) imagesToUpload.splice(index, 1);// 显示上传按钮if (imagesToUpload.length < MAX_IMAGES) {document.querySelector('.upload-btn').style.display = 'flex';}}// 提交上传所有图片function uploadAllImages() {if (!imagesToUpload.length) {alert("请上传至少一张图片");return;}const uploadedUrls = []; // 用于存储成功上传的图片 URLconst uploadedImagesPath = document.getElementById('uploaded-images-url');uploadedImagesPath.style.display = 'block';imagesToUpload.forEach((file, index) => {// 模拟上传过程const progressFill = document.querySelectorAll('.progress-fill')[index];progressFill.style.width = '0%';const formData = new FormData();formData.append("file", file);const xhr = new XMLHttpRequest();xhr.open("POST", "?act=up&t=", true);xhr.upload.onprogress = function(e) {if (e.lengthComputable) {const percentComplete = (e.loaded / e.total) * 100;progressFill.style.width = percentComplete + '%';}};xhr.onload = function() {if (xhr.status === 200) {const response = JSON.parse(xhr.responseText);if (response.success) {uploadedUrls.push(response.url);uploadedImagesPath.value = uploadedUrls.join('\n');} else {alert("上传失败:" + response.error);}}};xhr.send(formData);});}
</script></body>
</html>

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/58823.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java设计模式之创建者模式(5种)

设计模式 软件设计模式&#xff0c;又称为设计模式&#xff0c;是一套被反复利用&#xff0c;代码设计经验的总结&#xff0c;他是在软件设计过程中的一些不断发生的问题&#xff0c;以及该问题的解决方案。 **创建者模式又分为以下五个模式&#xff1a;**用来描述怎么“将对象…

如何一键更换ppt模板?掌握这2个ppt技巧快速搞定!

每当要制作ppt&#xff0c;很多人会第一时间去搜刮各种ppt模板&#xff0c;有时我们找到了一份貌似符合需求的模板&#xff0c;等到了ppt制作环节&#xff0c;才发现离我们的预期相距甚远&#xff0c;做到一半的ppt如何换模板呢&#xff1f; 想要在中途更换ppt模板&#xff0c;…

操作系统笔记(五)信号量,经典的IPC问题(读写者问题...)

信号量 一个信号量是一个包含两部分内容的数据结构&#xff1a; (a) 一个整数计数器, COUNT (b) 一个记录阻塞进程ID的队列, Q 信号量有两个原子操作&#xff1a; UP(V操作&#xff09; 和 DOWN (P操作) DOWN(S): if (S.count > 0) S.count …

臻于智境 安全护航 亚信安全受邀出席新华三智算新品发布会

近日&#xff0c;紫光股份旗下新华三集团在北京隆重举办了主题为“乘势 进化 臻于智境”的新华三智算新品发布会。作为新华三集团的长期战略合作伙伴&#xff0c;亚信安全受邀参会&#xff0c;亚信安全CEO马红军出席发布仪式&#xff0c;并与来自各界的业界伙伴共同探讨智能化…

【解决】Ubuntu18.04 卸载python之后桌面异常且终端无法打开,重启后进入tty1,没有图形化界面

我因为python版本太过于混乱 &#xff08;都是为了学习os&#xff09; &#xff0c;3.6—3.9版本我都安装了&#xff0c;指向关系也很混乱&#xff0c;本着“重装是最不会乱”的原则&#xff0c;我把全部版本都卸载了。然后装了3.9 发现终端打不开了&#xff0c;火狐浏览器的图…

2-140 基于Solidworks和Matlab Simulink Simscape仿真的机器人手臂仿真

基于Solidworks和Matlab Simulink Simscape仿真的机器人手臂仿真&#xff0c;使用Simulink-Simscape Multibody模块&#xff0c;完成SW-Simscape-Multibody-Link-Plugin手臂仿真&#xff0c;通过调节关节实现手臂动作&#xff0c;并显示三坐标位置。程序已调通&#xff0c;可直…

流媒体协议.之(RTP,RTCP,RTSP,RTMP,HTTP)(一)

闲着没事做&#xff0c;记录一下开发项目用过的协议&#xff0c;项目中&#xff0c;大多是是实时显示播放的&#xff0c;通过私有协议&#xff0c;传输到上位机&#xff0c;实时播放&#xff0c;延时小于200ms&#xff0c;仿照这些协议&#xff0c;定义的数据格式。如果用这些协…

通过思维导图【脑图】梳理Java 开发技术栈

通过思维导图【脑图】梳理Java 开发技术栈 前言一、思维导图概述二、Java 开发技术栈1.整体脑图结构2.基础知识3.核心语法4.高级特性5.常用框架6.数据库7.算法8.设计模式9.最佳实践10.资源推荐 附思维导图原件总结我是将军我一直都在&#xff0c;。&#xff01; 前言 将军深刻…

Mac “屏幕保护程序启动或显示器关闭后需要密码“无效

屏幕保护程序启动或显示器关闭后需要密码只能选择“立即”的解决方法&#xff1a; 在 iPhone mirror中设置&#xff0c;每次询问权限。 参考&#xff1a;https://support.apple.com/en-us/120421

基于matlab的凸包(Convex Hull)算法理解与测试

基于matlab的凸包Convex Hull算法理解与测试 0 引言1 Graham扫描算法原理2 Graham扫描算法实现3 Graham扫描算法关键函数4 结语 0 引言 &#x1f4bb;&#x1f4bb;AI一下&#x1f4bb;&#x1f4bb; 凸包算法是计算给定点集的最小凸包的一种算法。凸包是包含给定点集中所有点…

Conmi的正确答案——在Kibana中搜索Elasticsearch的索引

Elasticsearch版本&#xff1a;7.17.25 Kibana版本&#xff1a;7.17.25 0、进入首页 1、点击空间名“默”&#xff08;我的默认空间名就是“默认”&#xff09;&#xff1b; 2、点击气泡弹窗的“管理空间”进入管理页面&#xff1b; 3、点击“索引模式”&#xff0c;进入索引模…

QT访问数据库:应用提示Driver not loaded

在QT中运行完全正确错误截图 解决办法1 我用的是MySQL。我把libmysql.dll复制到应用程序的目录下&#xff0c;即可正常访问数据库。 解决办法2 bool open_work_db() {QString info "support drivers:";for (int i0; i<QSqlDatabase::drivers().size(); i){inf…

用图说明 CPU、MCU、MPU、SoC 的区别

CPU CPU 负责执行构成计算机程序的指令&#xff0c;执行这些指令所指定的算术、逻辑、控制和输入/输出&#xff08;I/O&#xff09;操作。 MCU (microcontroller unit) 不同的 MCU 架构如下&#xff0c;注意这里的 MPU 表示 memory protection unit MPU (microprocessor un…

你需要了解的Android repo工具

在 Android 开发中&#xff0c;repo 是 Google 用来管理多 Git 仓库的一种工具。Android 项目代码由多个 Git 仓库组成&#xff0c;repo 提供了一个高效的机制来批量管理这些仓库&#xff0c;尤其适用于大型项目和团队协作。 1. 什么是 Repo 工具&#xff1f; repo 是一个基于…

尚硅谷-react教程-求和案例-数据共享(下篇)-完成数据共享-笔记

#1024程序员节&#xff5c;征文# public/index.html <!DOCTYPE html> <html><head><meta charset"UTF-8"><title>redux</title></head><body><div id"root"></div></body> </html&…

Linux环境下Mongodb部署

文章目录 一、系统环境二、MongoDb安装添加MongoDB官方库安装MongoDB配置MongoDB 三、MongoDB常见操作四、MongoDB用户管理创建用户修改密码删除用户 五、启用安全控制六、备份与还原1. 备份2. 恢复 七、外部工具连接MongoDB 一、系统环境 CentOS Stream 9 64bit 二、MongoD…

LeetCode总结-链表

一、遍历链表 1290.二进制链表转整数 2058.找出临界点之间的最小和最大距离 2181.合并零之间的节点 二、删除节点 问&#xff1a;为什么没有修改 dummy&#xff0c;但 dummy.next 却是新链表的头节点&#xff1f;如果删除了 head&#xff0c;那么最后返回的是不是原链表的头…

项目模块十二:TcpServer模块

一、模块设计思路 1、目的 对所有模块整合&#xff0c;实现一个服务器模块供外部快速搭建服务器。 2、管理 监听套接字 主 Reactor&#xff0c;创建 EventLoop _baseloop 对象&#xff0c;进行对监听套接字的管理 哈希表管理所有新连接的 Channel 创建线程池进行连接的事…

保险大模型革新:全面自动化倒计时

摘 要 大模型于保险业不仅是一个技术升级的过程&#xff0c;更是一种商业模式的变革 未来将会是一切都连接着AI的世界——科技杂志《连线》创始主编凯文凯利&#xff08;KevinKelly&#xff09;曾在《5000天后的世界》中预测。 ChatGPT催生大模型热潮已将近两年&#xff0c;…

Elasticsearch —— ES 环境搭建、概念、基本操作、文档操作、SpringBoot继承ES

文章中会用到的文件&#xff0c;如果官网下不了可以在这下 链接: https://pan.baidu.com/s/1SeRdqLo0E0CmaVJdoZs_nQ?pwdxr76 提取码: xr76 一、 ES 环境搭建 注&#xff1a;环境搭建过程中的命令窗口不能关闭&#xff0c;关闭了服务就会关闭&#xff08;除了修改设置后重启的…