layui选择多张图片上传多图上传到服务器保存
多图上传在一些特殊的需求中我们经常会遇到,其实多图上传的原理大家都有各自的见解。对于Layui多图上传和我之前所说的通过js获取文本框中的文件数组遍历提交的原理一样,只不过是Layui中的upload.render方法已经帮我们封装好了,我们只管调用即可,也就是说你选中了几张图片,那么将会向后台请求与图片张数相同的次数,即为遍历提交的方式。
前端:
1 <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Test04.aspx.cs" Inherits="MyProject.Test04" %> 2 3 <!DOCTYPE html> 4 5 <html xmlns="http://www.w3.org/1999/xhtml"> 6 <head runat="server"> 7 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 8 <title>多图上传</title> 9 <meta name="renderer" content="webkit" /> 10 <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /> 11 <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0" /> 12 <link href="/JS/layui/css/layui.css?v=1.0" rel="stylesheet" /> 13 <link href="/layuiadmin/style/admin.css?v=1.0" rel="stylesheet" /> 14 <%--以下两条是弹confirm需要--%> 15 <link href="/css/bootstrap.min.css?v=1.0" rel="stylesheet" /> 16 <link href="/CSS/jquery-confirm.css?v=1.0" rel="stylesheet" /> 17 <script src="/JS/jquery-3.4.1.js?v=1.0"></script> 18 <script src="/JS/layui/layui.js?v=1.0"></script> 19 <script src="/JS/jquery-confirm.js?v=1.0"></script> 20 </head> 21 <body> 22 23 <div class="layui-fluid"> 24 <div class="layui-card"> 25 <div class="layui-card-body" style="padding: 15px;"> 26 <form class="layui-form"> 27 <div class="layui-card"> 28 <div class="layui-card-body"> 29 <div class="layui-tab layui-tab-card" lay-filter="component-tabs-card"> 30 <div class="layui-tab-content"> 31 <div class="layui-tab-item" style="display:block;"> 32 上传附件 33 <div class="layui-upload"> 34 <button type="button" class="layui-btn" id="multiple_img_upload">多图片上传</button> 35 <blockquote class="layui-elem-quote layui-quote-nm" style="margin-top: 10px; "> 36 预览: 37 <div class="layui-upload-list" id="div-slide_show"></div> 38 </blockquote> 39 </div> 40 </div> 41 </div> 42 </div> 43 </div> 44 </div> 45 <div class="layui-form-item layui-layout-admin"> 46 <div class="layui-input-block"> 47 <div class="layui-footer" style="left: 0; height:66px;"> 48 <button type="button" class="layui-btn sim_btn">提交</button> 49 <input type="button" id="btnReset" class="layui-btn layui-btn-primary" value="重置" /> 50 </div> 51 </div> 52 </div> 53 </form> 54 55 </div> 56 </div> 57 </div> 58 59 <input type="hidden" name="imgs" class="multiple_show_img" value="" /><%--用于保存多图上传的资源数组--%> 60 61 <script type="text/javascript"> 62 //这里一定要设置全局变量,不然下面用的时候,未定义 63 var multiple_images = []; 64 var layer, form, laypage, laydate, upload, layedit, indexs, indexsMan, element; 65 $(function () { 66 layui.use(['form', 'layedit', 'upload'], function () { 67 layedit = layui.layedit, 68 form = layui.form, 69 upload = layui.upload; 70 71 //多图片上传 72 upload.render({ 73 elem: '#multiple_img_upload' 74 , url: "/ASHX/SetImg.ashx?actionMore=MoreIMG" 75 , multiple: true 76 , before: function (obj) { 77 78 var files = obj.pushFile(); //将每次选择的文件追加到文件队列 79 //var len = getJsonLength(files); 80 var fileAllNum = 10;//允许每次上传附件的数量 81 var yishangchuan = $('.multiple_show_img').val();//已经上传完的图片的路径集合,多个以,号分隔 82 var arrImgNum = 0;//计算出共几张图 83 if (yishangchuan != "") { 84 if (yishangchuan.indexOf(",") > 0) {//如果有至少2张图片 85 arrImgNum = yishangchuan.split(',').length;//计算出共几张图 86 } 87 } 88 //arrImgNum = arrImgNum == arrImgNum ? 2 : arrImgNum; 89 //alert(arrImgNum); 90 //alert(len); 91 //alert(fileAllNum); 92 if (arrImgNum < fileAllNum) { 93 //预读本地文件示例,不支持ie8 94 obj.preview(function (index, file, result) { 95 $('#div-slide_show').append('<img src="' + result + '" id="' + file.name + '" name="' + file.name + '" alt="' + file.name + '" title="点击删除" class="layui-upload-img" style="width: 100px;height: 100px;" onclick="delMultipleImgs(this)" onmouseover="imgover(this)" onmouseout="imgout(this)" /> ') 96 delete files[index];//删除列表中已经上传过的对应的文件,一般在某个事件中使用;防止重复上次预览的数据进行的提交问题。 97 }); 98 } 99 else { 100 layer.msg("上传文件最大不允许超过" + fileAllNum + "个"); 101 return false; 102 } 103 } 104 , done: function (res) { 105 //如果上传成功 106 //alert(index); 107 if (res.State == true) { 108 //追加图片成功追加文件名至图片容器1647508248937-0 1647508263902-0 1647508248937-0 109 //alert(res.Data); 110 multiple_images.push(res.Data); 111 $('.multiple_show_img').val(multiple_images);//把多选择的图片的地址统一放这里 112 113 //$('.multiple_show_img').val(""); 114 //multiple_images = []; 115 //delete this.files[index]; 116 } else { 117 //提示信息 118 layer.msg(res.Message); 119 } 120 } 121 }); 122 //多图片上传 123 124 });//对应layui.use(['index', 'layer', 'form', 'laypage', 'laydate', 'upload', 'jquery', 'layedit'], function () { 125 126 127 //提交表单 128 $("body").on("click", ".sim_btn", function () { 129 SaveData(); 130 }); 131 132 });//对应$(function () {//对应$(function () {//对应$(function () {//对应$(function () {//对应$(function () {//对应$(function () {//对应$(function () {//对应$(function () {//对应$(function () {//对应$(function () {//对应$(function () {//对应$(function () {//对应$(function () {//对应$(function () { 133 134 135 function SaveData() {// 136 /上传附件开始/ 137 138 var uploadFiles = $('.multiple_show_img').val();//把上传附件多选择的图片的地址统一放这里 139 alert(uploadFiles); 140 return false; 141 /上传附件结束/ 142 143 //if (names == "") { 144 // errorMsg = "请输入姓名"; 145 //} 146 //alert(errorMsg); 147 //return false; 148 if (errorMsg != "") { 149 layer.msg(errorMsg, { icon: 7 }); 150 return false; 151 } else { 152 loadIndex = layer.load(0); 153 var url = "/ClinicalControl/Case_ADD.aspx"; 154 var data = { 155 'action': 'SaveData' 156 , 'id': id 157 , 'uploadFiles': uploadFiles 158 , 'updateCRIDMan': updateCRIDMan 159 //, 'test': test 160 //, 'test': test 161 } 162 $.ajax({// 163 type: "POST", 164 url: url, 165 dataType: "JSON", 166 data: data, 167 success: function (result) { 168 if (result.State) { 169 layer.close(loadIndex); 170 if (result.Data != "") { 171 layer.msg(result.Data, { icon: 7 }); 172 } 173 else { 174 layer.msg("操作成功", { icon: 6 }); 175 } 176 setTimeout(closeRefresh, 1000);//关闭当前iframe,刷新指定iframe 177 } 178 else { 179 layer.msg(result.Data, { icon: 7 }); 180 } 181 }, complete: function (result) { 182 layer.close(loadIndex); 183 } 184 }); 185 } 186 187 } 188 189 //单击图片删除图片 【注册全局函数】 190 function delMultipleImgs(this_img) { 191 $.confirm({ 192 title: '提示', 193 content: '确定要删除吗?', 194 confirm: function () { 195 //获取下标 196 var subscript = $("#div-slide_show img").index(this_img); 197 //删除图片 198 this_img.remove(); 199 //删除数组 200 multiple_images.splice(subscript, 1); 201 //重新排序 202 multiple_images.sort(); 203 $('.multiple_show_img').val(multiple_images); 204 }, 205 cancel: function () { 206 layer.msg("操作取消", { icon: 6 }); 207 } 208 }); 209 210 //返回 211 return; 212 } 213 //上传附件鼠标悬停提示框 214 function openMsg01(tempid) { 215 subtips01 = layer.tips('点击图片删除', '#div-slide_show', { tips: [1, '#ff6700'], time: 30000 }); 216 } 217 //鼠标悬停提示框 218 function imgover(img) { 219 openMsg01(""); 220 } 221 function imgout(img) { 222 layer.close(subtips01); 223 } 224 225 </script> 226 </body> 227 </html> 228
/ASHX/SetImg.ashx文件
1 using Common; 2 using Model; 3 using System; 4 using System.Drawing; 5 using System.IO; 6 using System.Web; 7 8 namespace MyProject.ASHX 9 { 10 /// <summary> 11 /// SetImg 的摘要说明 12 /// </summary> 13 public class SetImg : IHttpHandler 14 { 15 16 public void ProcessRequest(HttpContext context) 17 { 18 string action = ""; 19 string actionMore = ""; 20 context.Response.ContentType = "text/plain"; 21 if (context.Request.Form["action"]!=null) 22 { 23 action = context.Request.Form["action"].ToString();//AJAX传参 24 } 25 if (context.Request["actionMore"] != null) 26 { 27 actionMore = context.Request["actionMore"].ToString();//URL传参 28 } 29 30 switch (action) 31 { 32 case "ConvertIMG": 33 ConvertIMG(context); 34 break; 35 default: 36 break; 37 } 38 switch (actionMore)//多图上传 39 { 40 case "MoreIMG": 41 MoreIMG(context); 42 break; 43 default: 44 break; 45 } 46 47 48 } 49 50 /// <summary> 51 /// 单张图片上传 52 /// </summary> 53 /// <param name="context"></param> 54 public void ConvertIMG(HttpContext context) 55 { 56 string imgurl = context.Request.Form["imgurl"].ToString(); 57 string strFilePath = ""; 58 string strReturnFilePath = "";//返回前端的路径,用于存入SQL 59 string imgname = ""; 60 if (imgurl.IndexOf("data:image") >= 0) 61 { 62 string base64 = imgurl.Split(',')[1];//规范化,逗号前面的是标识符,用于说明原图片的名字和格式 63 string path = context.Server.MapPath("/");//获取网站的根路径 64 string strRand = PublicHelper.RanStr(10, true); 65 string strSuffix = ".jpg"; //文件的后缀名根据实际情况 66 strReturnFilePath = "\\UploadFile\\" + System.DateTime.Now.Year.ToString() + "\\" + System.DateTime.Now.Month.ToString() + "\\" + System.DateTime.Now.Day.ToString() + "\\"; 67 string strPath = path + strReturnFilePath;//在本地硬盘的绝对路径 68 imgname = strRand + strSuffix; 69 if (!System.IO.Directory.Exists(strPath)) 70 { 71 System.IO.Directory.CreateDirectory(strPath); 72 } 73 //string local = "UploadFile\\" + System.DateTime.Now.Year.ToString() + "\\" + System.DateTime.Now.Month.ToString() + "\\" + System.DateTime.Now.Day.ToString() + "\\"; 74 //strFilePath = "/UploadFile/" + DateTime.Now.ToString("yyyyMMdd") + strRand + strSuffix; 75 strFilePath = strPath.Trim().Replace("\\", "/"); 76 strReturnFilePath = strReturnFilePath.Trim().Replace("\\", "/") + imgname; 77 MemoryStream stream = new MemoryStream(Convert.FromBase64String(base64)); 78 Bitmap bit = new Bitmap(stream); 79 bit.Save(strPath + imgname);//保存图片到本地 80 } 81 82 ResultInfo resultInfo = new ResultInfo() { State = false }; 83 if (strFilePath != "") 84 { 85 resultInfo.Data = strReturnFilePath; 86 resultInfo.State = true; 87 } 88 string resultJson = JsonHelper.ObjectToJSON(resultInfo); 89 context.Response.Write(resultJson); 90 context.Response.End(); 91 } 92 93 /// <summary> 94 /// 多张图片上传 95 /// </summary> 96 /// <param name="context"></param> 97 public void MoreIMG(HttpContext context) 98 { 99 string strFilePath = ""; 100 if (context.Request.Files.Count > 0) 101 { 102 //HttpPostedFile f = context.Request.Files[0]; 103 //f.SaveAs(context.Server.MapPath(f.FileName)); 104 105 ResultInfo resultInfo = new ResultInfo() { State = false }; 106 int isCheck = 0;//上传附件是否通过验证 107 var file = context.Request.Files[0]; 108 string extension = System.IO.Path.GetExtension(file.FileName);//获取文件后缀名FileSize 109 string strFileExtension = PublicHelper.GetValue("FileExtension");//配置文件允许上传的附件类型 110 string strFileSize = PublicHelper.GetValue("FileSize");//配置文件允许上传的附件类型 111 112 if (strFileExtension.IndexOf(extension.ToLower()) < 0) 113 { 114 isCheck = 1; 115 resultInfo.Message = "不支持此附件类型"; 116 } 117 if (file.ContentLength > Convert.ToInt32(strFileSize)) 118 { 119 isCheck = 1; 120 resultInfo.Message = "上传附件过大"; 121 } 122 if (isCheck == 0) 123 { 124 //定义本地路径位置 125 string local = "UploadFile\\" + System.DateTime.Now.Year.ToString() + "\\" + System.DateTime.Now.Month.ToString() + "\\" + System.DateTime.Now.Day.ToString() + "\\"; 126 //string filePathName = string.Empty; 127 string localPath = Path.Combine(HttpRuntime.AppDomainAppPath, local); 128 129 //var tmpName = HttpContext.Current.Server.MapPath("~/UploadFile/" + strCFID + "/" + System.DateTime.Now.ToString("yyyyMMdd") + "/"); 130 //var tmp = file.FileName; 131 //var tmpIndex = 0; 132 133 //不带路径的最终文件名 134 string strRand = PublicHelper.RanStr(10, true); 135 string filePathName = strRand + PublicHelper.FilterSQL(file.FileName);//过滤文件名中的SQL敏感字符 136 if (!System.IO.Directory.Exists(localPath)) 137 { 138 System.IO.Directory.CreateDirectory(localPath); 139 } 140 //if (System.IO.Directory.Exists(localPath)) 141 //{ 142 // string a1 = ""; 143 //} 144 //else 145 //{ 146 // System.IO.Directory.CreateDirectory(localPath); 147 //} 148 string localURL = Path.Combine(local, filePathName); 149 file.SaveAs(Path.Combine(localPath, filePathName)); //保存图片(文件夹) 150 151 152 resultInfo.Data = "/" + localURL.Trim().Replace("\\", "/"); 153 resultInfo.State = true; 154 resultInfo.Message = ""; 155 } 156 157 string resultJson = JsonHelper.ObjectToJSON(resultInfo); 158 context.Response.Write(resultJson); 159 context.Response.End(); 160 161 } 162 163 //string imgurl = context.Request.Form["imgurl"].ToString(); 164 //if (imgurl.IndexOf("data:image") >= 0) 165 //{ 166 // string base64 = imgurl.Split(',')[1];//规范化,逗号前面的是标识符,用于说明原图片的名字和格式 167 // string path = context.Server.MapPath("/");//获取网站的根路径 168 // string strRand = PublicHelper.RanStr(10, true); 169 // string strSuffix = ".jpg"; //文件的后缀名根据实际情况 170 // string strPath = path + "\\UploadFile\\" + DateTime.Now.ToString("yyyyMMdd") + strRand + strSuffix; 171 // strFilePath = "/UploadFile/" + DateTime.Now.ToString("yyyyMMdd") + strRand + strSuffix; 172 // MemoryStream stream = new MemoryStream(Convert.FromBase64String(base64)); 173 // Bitmap bit = new Bitmap(stream); 174 // bit.Save(strPath);//保存图片到本地 175 //} 176 177 //ResultInfo resultInfo = new ResultInfo() { State = false }; 178 //if (strFilePath != "") 179 //{ 180 // resultInfo.Data = strFilePath; 181 // resultInfo.State = true; 182 //} 183 //string resultJson = JsonHelper.ObjectToJSON(resultInfo); 184 //context.Response.Write(resultJson); 185 //context.Response.End(); 186 } 187 188 189 public bool IsReusable 190 { 191 get 192 { 193 return false; 194 } 195 } 196 197 } 198 }
PublicHelper.RanStr(10, true);方法
1 /// <summary> 2 /// 获取随机字符串 3 /// </summary> 4 /// <param name="Length">生成长度</param> 5 /// <param name="Sleep">是否要在生成前将当前线程阻止以避免重复</param> 6 /// <returns></returns> 7 public static string RanStr(int Length, bool Sleep) 8 { 9 if (Sleep) 10 System.Threading.Thread.Sleep(3); 11 char[] Pattern = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' }; 12 string result = ""; 13 int n = Pattern.Length; 14 System.Random random = new Random(~unchecked((int)DateTime.Now.Ticks)); 15 for (int i = 0; i < Length; i++) 16 { 17 int rnd = random.Next(0, n); 18 result += Pattern[rnd]; 19 20 } 21 return result; 22 }
PublicHelper.FilterSQL(file.FileName);
1 /// <summary> 2 /// 后台过滤SQL关键字 3 /// </summary> 4 /// <param name="str">参数SQL语句</param> 5 /// <returns></returns> 6 public static string FilterSQL(string str) 7 { 8 //string filterSQL = "'|and|exec|insert|select|delete|update|count | *|%| chr | mid | master | truncate | char | declare |;| or | -| + | ,"; 9 string filterSQL = "exec|insert|delete|update|count|*|chr|mid|master|truncate|char|declare|;"; 10 string[] strArray = filterSQL.Split('|'); 11 12 for (int i = 0; i < strArray.Length; i++) 13 { 14 if (str.IndexOf(strArray[i]) >= 0) 15 { 16 str = str.Replace(strArray[i], ""); 17 } 18 } 19 return str; 20 }
配置文件
1 <?xml version="1.0" encoding="utf-8"?> 2 <appSettings> 3 <!--允许上传的附件类型--> 4 <add key="FileExtension" value=".jpg.jpeg.gif.png.bmp" /> 5 <!--允许每次上传附件的大小,以byte为单位,1048576是一M。--> 6 <add key="FileSize" value="10485760" /> 7 <!--允许批量上传附件的数量--> 8 <add key="FileAllNum" value="3" /> 9 </appSettings>