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

前端技术(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博客

相关文章:

  • iOS rootless无根越狱检测方案
  • Python中的JSON转换:全面指南与最佳实践
  • ESLint报错:Could not find config file.
  • Git合并删除原理
  • Centos与Ubuntu系统的对比分析
  • C++进制转换的方法
  • LinuxI/O多路转接(select、poll、epoll)
  • 23种设计模式-模板方法(Template Method)设计模式
  • 基于无线的分布式温度采集报警系统设计(论文+源码)
  • SpringCould微服务架构之Docker(3)
  • QML学习 —— 17、“DelayButton 延迟按钮“之“一键三连“示例(附完整源码)
  • vue2项目eslint提示<template v-for> key should be placed on the <template> tag
  • vue 3 深度指南:从基础到全栈开发实践
  • Git 基础入门:从概念到实践的版本控制指南
  • 【PostgreSQL内核学习 —— (sort算子)】
  • 练习:求质数
  • Nacos Config Service 和 Naming Service 各自的核心功能是什么?
  • SpringCloud微服务框架搭建详解(基于Nacos)
  • Scala
  • 洛谷1449c语言
  • 天津建设工程招标信息网官网/新塘网站seo优化
  • 网站页脚需要放什么用/企业seo整站优化方案
  • 网站图片被盗连怎么办/南宁百度seo排名优化软件
  • 物流网站开发系统论文/如何注册网站怎么注册
  • 我国企业网站的建设情况/湖北搜索引擎优化
  • win2012 iis 新建网站/杭州网站seo