当前位置: 首页 > article >正文

前端技术(28) : 拖拽、粘贴和点击浏览文件上传

基于静态的vue及element-ui, 下载参考: 前端技术(27) : 纯HTML使用Element UI_html引入element ui-CSDN博客

HTML

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>拖拽浏览粘贴上传文件</title>
		<link rel="stylesheet" href="element-ui/theme-chalk/index.css">
		<style>
			/*文件上传*/
			#drop-area {
				border: 2px dashed #ccc;
				border-radius: 10px;
				width: 300px;
				padding: 20px;
				text-align: center;
				margin: 50px auto;
			}

			.gallery-item {
				position: relative;
				display: inline-block;
				margin: 10px;
				border: 1px solid #ddd;
				border-radius: 5px;
				padding: 5px;
				background-color: white;
			}

			.thumb {
				width: 100px;
				height: auto;
				border-radius: 5px;
			}

			.delete-btn {
				position: absolute;
				top: 5px;
				right: 5px;
				cursor: pointer;
				color: red;
				font-size: 16px;
				background-color: rgba(255, 255, 255, 0.7);
				border-radius: 50%;
				width: 20px;
				height: 20px;
				display: flex;
				justify-content: center;
				align-items: center;
			}

			.file-info {
				text-align: center;
				white-space: pre-wrap;
			}


			/* 图片点击放大 */
			.overlay {
				position: fixed;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				background-color: rgba(0, 0, 0, 0.7);
				display: none;
				justify-content: center;
				align-items: center;
				z-index: 9999;
			}

			.overlay img {
				max-width: 90%;
				max-height: 90%;
				cursor: pointer;
			}
		</style>
	</head>
	<body>

		<div class="overlay" onclick="closeOverlay()">
			<img id="enlargedImg" src="">
		</div>
		<div id="app">
			<div>
				<div id="drop-area" style="width: 800px;height: 300px;">
					<br><br><br><br><br>
					粘贴文件到这里、
					或拖拽文件到这里<br><br>或<span style="color: blue;cursor: pointer;" onclick="selectFile()">选择文件</span>

					<input type="file" id="fileElem" multiple onchange="handleFiles(this.files)" style="display:none">
				</div>
				<div id="gallery"></div>
			</div>
		</div>
	</body>
	<script src="js/vue.js"></script>
	<script src="element-ui/index.js"></script>
	<script src="js/axios.min.js"></script>
	<script src="js/jquery-latest.js"></script>
	<script>
		host = 'http://127.0.0.1:7001'

		function c(data) {
			console.log(data)
		}

		var vue = new Vue({
			el: '#app',
			data() {
				return {}
			},
			created() {},
			methods: {
				initLoading() {
					this.loadingInstance = this.$loading({
						lock: true,
						text: '加载中',
						spinner: 'el-icon-loading',
						background: 'rgba(0, 0, 0, 0.7)',
					});
				},
				showLoading() {
					this.initLoading();
				},
				hideLoading() {
					if (this.loadingInstance) {
						this.loadingInstance.close()
						this.loadingInstance = null
					}
				}
			}
		})

		// 文件上传
		// 文件上传
		const dropArea = document.getElementById('drop-area');
		const fileElem = document.getElementById('fileElem');
		const gallery = document.getElementById('gallery');
		var filesMap = new Map();
		var fileNameItemMap = new Map();


		// 拖拽相关事件处理
		['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
			dropArea.addEventListener(eventName, preventDefaults, false);
		});

		function selectFile() {
			fileElem.click()
		}

		function preventDefaults(e) {
			e.preventDefault();
			e.stopPropagation();
		}

		dropArea.addEventListener('drop', handleDrop, false);

		function handleDrop(e) {
			let dt = e.dataTransfer;
			let files = dt.files;

			handleFiles(files);
		}

		function handleFiles(files) {
			vue.showLoading();
			[...files].forEach(uploadFile);
			vue.hideLoading();
			c(filesMap)
		}

		function uploadFile(file) {
			let reader = new FileReader();

			const formData = new FormData();
			formData.append('file', file);
			const xhr = new XMLHttpRequest();
			xhr.open('POST', host + '/api/upload', true); // 替换为你的后端API地址

			xhr.onload = function() {
				if (xhr.status === 200) {
					const jsonResponse = JSON.parse(xhr.responseText).data;
					filesMap.set(jsonResponse.file_name, jsonResponse.url)
					history_item = fileNameItemMap.get(file.name)
					if (history_item != null) {
						gallery.removeChild(history_item);
						fileNameItemMap.delete(file.name)
					}

					let item = document.createElement('div');
					fileNameItemMap.set(file.name, item)
					item.className = "gallery-item";

					if (file.type.match('image.*')) {
						let img = document.createElement('img');
						img.src = jsonResponse.url;
						img.title = file.name;
						img.style.cursor = 'pointer';
						img.className = "thumb";
						item.appendChild(img);
						img.onclick = function() {
							enlargeImage(jsonResponse.url)
						};
					} else {
						let fileInfo = document.createElement("div");
						fileInfo.style.cursor = 'pointer';
						fileInfo.className = "file-info";
						fileInfo.textContent = file.name + '    ';
						// 添加点击事件监听器
						fileInfo.addEventListener('click', function() {
						    // 在新标签页打开指定URL
						    window.open(jsonResponse.url, '_blank');
						});
						item.appendChild(fileInfo);
					}

					let deleteBtn = document.createElement('span');
					deleteBtn.className = 'delete-btn';
					deleteBtn.textContent = '×';
					deleteBtn.onclick = function() {
						removeItem(item, file);
					};
					item.appendChild(deleteBtn);

					gallery.appendChild(item);
					vue.fileName = [...fileNameItemMap.keys()].join('|')
				} else {
					console.log('An error occurred during the transaction');
				}
			};

			xhr.send(formData);
		}

		function getFormattedDateTime() {
			const now = new Date();

			const year = now.getFullYear();
			const month = String(now.getMonth() + 1).padStart(2, '0'); // 月份从0开始,所以要加1
			const day = String(now.getDate()).padStart(2, '0');
			const hours = String(now.getHours()).padStart(2, '0');
			const minutes = String(now.getMinutes()).padStart(2, '0');
			const seconds = String(now.getSeconds()).padStart(2, '0');

			return `${year}${month}${day}${hours}${minutes}${seconds}`;
		}


		// 处理粘贴事件
		document.body.addEventListener('paste', function(event) {
			for (let i = 0; i < event.clipboardData.items.length; i++) {
				let item = event.clipboardData.items[i];
				if (item.kind === 'file') {
					let file = item.getAsFile();
					console.log(file.name)
					if(file.name === 'image.png'){
						let newFile = new File([file], getFormattedDateTime() + '.png', {
							type: file.type
						});
						uploadFile(newFile);
					}else{
						uploadFile(file);
					}
				}
			}
		});

		function removeItem(item, file) {
			gallery.removeChild(item);
			fileNameItemMap.delete(file.name);
			vue.fileName = [...fileNameItemMap.keys()].join('|');
			filesMap.delete(file.name);
		}

		function enlargeImage(img) {
			var overlay = document.querySelector(".overlay");
			var enlargedImg = document.getElementById("enlargedImg");

			enlargedImg.src = img;
			overlay.style.display = "flex";
		}

		function closeOverlay() {
			var overlay = document.querySelector(".overlay");
			overlay.style.display = "none";
		}
	</script>
</html>

接口(python) 

python(26) : 文件上传及下载和预览-CSDN博客


http://www.kler.cn/a/612584.html

相关文章:

  • 3大支柱+8种方法:拆解分布式系统性能优化的底层逻辑
  • 谷歌决定终止开源Android
  • 【黑皮书】 AVL树
  • kafka部署手册
  • 关于ArcGIS中加载影像数据,符号系统中渲染参数的解析
  • HarmonyOS:GridObjectSortComponent(两个Grid之间网格元素交换)
  • 深度探秘K8s服务(Service):架构基石与应用实践
  • 【LeetCode 热题 100】解答汇总
  • 苏宁开放平台关键字搜索接口接入教程‌
  • springboot 四层架构之间的关系整理笔记一
  • es 3期 第27节-运用Script脚本实现复杂需求
  • 简记_FPGA 硬件最小系统设计
  • Springbean(二)@Component及其派生注解自动注入(2)使用注意和加载问题
  • 一周掌握Flutter开发--8. 调试与性能优化(下)
  • 计算机网络--传输层(1)
  • html dom 的 event 事件
  • 【Elasticsearch基础】基本核心概念介绍
  • [实操]MySQL8 读写分离后,配合redis的方法与步骤
  • pnpm 依赖升级终极指南:从语义化版本控制到 Monorepo 全局更新的企业级实践
  • ComfyUi教程之阿里的万象2.1视频模型