最近一段时间都在使用PlUpload做文件上传的功能,研究过后感觉使用起来体验还是比较好的,不过网上的资料很多都记录的很简便,故此记录一下,方便自己使用,也给需要的朋友提供多一个文件上传的选择。由于这篇文章比较长,我遇到坑的地方就不给大家一一举例了,要是小伙伴们想经历的话,可以先不看文章,自己去尝试一下。附上一篇中文介绍文档:https://www.cnblogs.com/2050/p/3913184.html;话不多说,直接上代码:
这部分是我页面上的代码,由于为了方便使用,我的上传写成了一个用户控件,页面上只需要引用即可,UploadControl是引用控件的部分:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="FileUpload.aspx.cs" Inherits="EPC.FileManager.Page.FileUpload" %> <%@ Register Src="~/UserControls/UploadControl.ascx" TagPrefix="uc1" TagName="UploadControl" %> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title></title> </head> <body> <form id="form1" runat="server"> <div> <uc1:UploadControl runat="server" ID="UploadControl" /> </div> </form> </body> </html>
这一块是我的上传控件部分:
首先是需要添加的引用:
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="UploadControl.ascx.cs" Inherits="EPC.FileManager.UserControls.UploadControl" %> <link href="../Themes/CSS/reset.css" rel="stylesheet" /> <link href="../Themes/CSS/index.css" rel="stylesheet" /> <script src="../Scripts/jQuery/jquery-1.11.1.min.js"></script> <script src="../Scripts/plupload/plupload.full.min.js"></script> <script src="../Scripts/jQuery/index.js"></script> <!--用于保存所有上传成功的文件的URL--> <input type="hidden" id="fileUploadUrl" runat="server" />
然后是我的上传文件的界面布局,你们也可以自己更改为自己喜欢的风格,放上来只是为了便于讲解:
<section class="center-box"> <div class="container"> <div class="center clearfix"> <div class="line-lebel"> 文件上传: </div> <div class="line-box"> <!--上传下载开始--> <div class="J-upload-box clearfix"> <div class="J-upload-area"> <div class="J-need-upload-file clearfix"> <div class="J-handle-btns"> <b class="J-continue-add" id="choseFileBtn"><i id="JcontinueAdd">选择文件</i> </b> <b class="J-to-upload" id="JToUpload">开始上传</b> </div> </div> <div class="J-show-the-name clearfix" style="display: none;"> <!--选择文件和图片的时候 显示文件名--> <div class=" " id="JShowFileBox"> <div class="J-folding"><span>收起<i></i></span></div> <ul class="J-file-img J-calc-len clearfix" id="JShowFileImg"> <%--<li title="J-folding.png"> <em>J-folding.png</em><span></span> </li>--%> </ul> </div> <!--只选择图片时--> <div class="J-imgs-box" id="JShowImgsBox"> <ul class="J-imgs J-calc-len clearfix" id="JShowImgs"> <%--<li title="2.jpg"> <em> <img src="img/1.jpg"></em><span></span> </li> --%> </ul> </div> </div> </div> <!--进度条--> <div class="ProgressBar" style="display: none"> <div id="progress" style="width: 0%"></div> </div> <!--用户点击“开始上传”后的展示区域(已上传文件展示开始)--> <div class="J-show-all " id="JShowAll" style="display: none;"> <div class="J-show-all-center"> <div class="J-title" id="JTitle">已完成上传</div> <!--选择文件和图片的时候 显示文件名--> <div class="J-file-img-box "> <div class="J-folding"><span>收起<i></i></span></div> <ul class="J-file-img J-calc-len clearfix" id="JUploadFileImg"> </ul> </div> <!--只选择图片时--> <div class="J-imgs-box"> <ul class="J-imgs J-calc-len clearfix" id="JUploadImgs"> </ul> </div> </div> </div> <!--已上传文件展示结束--> </div> </div> <!--上传下载结束--> </div> </div> </section>
界面效果是这样的,比较简陋,haha...:
这个部分就是plupload控件的核心了,这个对象有许多的方法,大家可以根据自己的需求去研究和使用:
<script> // 实例化一个plupload上传对象,并根据需要进行相应的设置: var uploader = new plupload.Uploader({ // 触发文件选择对话框的按钮,为哪个元素id browse_button: 'choseFileBtn', // 服务器端的上传页面地址,路径根据自己的实际情况配置 url: '../Handler/UploadHandler.ashx', // swf文件,当需要使用swf方式进行上传时需要配置该参数 flash_swf_url: '../Scripts/plupload/moxie.swf', // silverlight文件,当需要使用silverlight方式进行上传时需要配置该参数 silverlight_xap_url: '../Scripts/plupload/moxie.xap', // 文件大小及类型相关设置 filters: { // 最大只能上传200mb的文件 max_file_size: '200mb', // 不允许队列中存在重复文件 prevent_duplicates: true, // 允许上传的文件类型 mime_types: [{ title: 'FileTypes', extensions: 'doc,xls,xlsx,jpg,gif,png,jpeg,zip,rar' }] } }); // 在实例对象上调用init()方法进行初始化 uploader.init(); // 文件上传前 uploader.bind('FilesAdded', function (uploader, files) { // 判断是否包含文件 var isFile = false; // 判断是否包含图片 var isPic = false; // 定义一个数组存放文件类型,这里我暂时还没想到怎么获取文件类型,所以用一个固定的代替,好像这个控件里面有些jQuery的函数使用不了,再研究下 var picTypeArr = ["image/png", "image/jpeg", "image/jpg"]; // 根据文件类型选择展示框 for (var i = 0; i < files.length; i++) { isPic = false; // 获取文件类型 var fileType = files[i].type; // 判断文件类型是图片还是文件(暂时指定数组中的三种类型为图片类型,其它默认为文件类型) for (var j = 0; j < picTypeArr.length; j++) { if (picTypeArr[j] == fileType) { isPic = true; } } // 根据文件类型选择文件展示框 if (isPic == true) { // 拼接文件展示框HTML var html = '<li title="' + files[i].name + '" id="' + files[i].id + '"><em></em><span class="del_WaitUpload" FileId="' + files[i].id + '"></span></li>'; // 展示待上传图片 $("#JShowImgs").append(html); !function (i) { // 图片预览(图片预览目前仅支持以上三种图片类型,大家可以再研究下其它图片类型怎么预览) previewImage(files[i], function (imgsrc) { $('#' + files[i].id).find("em").append('<img class="imgZoom" src="' + imgsrc + '" />'); }) }(i); } else { var html = '<li title="' + files[i].name + '" id="' + files[i].id + '"><em>' + files[i].name + '</em><span class="del_WaitUpload" FileId="' + files[i].id + '"></span></li>'; // 展示待上传文件 $("#JShowFileImg").append(html); } } // 获取点击“开始上传”后待上传文件展示区域文件的个数 var waitUploadFileLiLen = $("#JShowFileImg").find('li').length; var waitUploadPicLiLen = $("#JShowImgs").find("li").length; // 待上传的文件如果不为空,展示待上传文件展示框, if (waitUploadFileLiLen > 0 || waitUploadPicLiLen > 0) { $(".J-show-the-name").show(); } // 重新计算待上传的文件展示宽度(针对图片展示框),这个方法在index.js文件中 Funs.setImgWidth($("#JShowImgs li")); }); // 文件上传过程中不断触发,用来显示上传进度 uploader.bind('UploadProgress', function (uploader, file) { // 禁用选择文件和开始上传按钮 $("#choseFileBtn").attr("disabled", true); $("#JToUpload").attr("disabled", true); // 展示进度条(这个进度条是随意写的,大家可以自行替换为自己想要的效果) uploadProcess(file.percent); }); // 当队列中的某一个文件正要开始上传前触发 uploader.bind('BeforeUpload', function (uploader, file) { // 禁用选择文件和开始上传按钮 $("#choseFileBtn").attr("disabled", true); $("#JToUpload").attr("disabled", true); // 清理进度条 clearProcess(); }); // 队列中的某一个文件上传完成后触发 uploader.bind('FileUploaded', function (uploader, file, responseObject) { // 接收上传响应信息 var resp = JSON.parse(responseObject.response) // 判断上传是否成功 if (resp.StatusCode == 1) { // 判断是否包含图片 var isPic = false; // 定义两个数组存放文件类型 var picTypeArr = [".png", ".jpeg", ".jpg"]; // 判断文件类型是图片还是文件 for (var j = 0; j < picTypeArr.length; j++) { //isPic = false; if (picTypeArr[j] == resp.FileType) { isPic = true; } } // 根据文件类型选择展示框 if (isPic == true) { // 上传成功,展示已上传图片 var html = '<li title="' + resp.FileName + '"><em><img src="' + resp.FileUrl + '"></em><span class="del_Uploaded" fileurl="' + resp.FileUrl + '"></span></li>'; $("#JUploadImgs").append(html); } else { // 上传成功,展示已上传文件 var html = '<li title="' + resp.FileName + '" ><em><a href="' + resp.FileUrl + '">' + resp.FileName + '</a></em><span class="del_Uploaded" fileurl="' + resp.FileUrl + '"></span></li>'; // 展示已完成上传文件 $("#JUploadFileImg").append(html); } // 判断已上传文件展示框是否为空,不为空则展示 var uploadFileLiLen = $("#JUploadFileImg").find("li").length; var uploadPicLiLen = $("#JUploadImgs").find("li").length; if (uploadFileLiLen > 0 || uploadPicLiLen > 0) { // 展示已上传文件展示框 $("#JShowAll").show(); // 清除进度条并隐藏 clearProcess(); // 删除上传队列中文件(注意:上传成功后必须移除uploader对象中的文件,否则会对之后的上传功能造成影响) uploader.removeFile(file); // 移除对应的待上传文件展示框li $("#" + file.id + "").remove(); // 判断待上传文件展示框是否为空,为空则隐藏 var waitUploadFileLiLen = $("#JShowFileImg").find('li').length; var waitUploadPicLiLen = $("#JShowImgs").find("li").length; if (waitUploadFileLiLen == 0 && waitUploadPicLiLen == 0) { // 隐藏待上传文件展示框 $(".J-show-the-name").hide(); } // 保存已上传文件的URL var fileUrl = $("#UploadControl_fileUploadUrl").val(); if (fileUrl != null && fileUrl != "") { $("#UploadControl_fileUploadUrl").val($("#UploadControl_fileUploadUrl").val() + "," + resp.FileUrl) } else { $("#UploadControl_fileUploadUrl").val(resp.FileUrl) } } } else { // 弹出上传失败的提示信息 alert(resp.Message); clearProcess(); return; } }); // 当上传队列中所有文件都上传完成后触发 uploader.bind('UploadComplete', function (uploader, files) { // 取消禁用选择文件和开始上传按钮 $("#upload-btn-add").attr("disabled", false); $(".upload-btn").attr("disabled", false); // 删除已上传文件 $(".del_Uploaded").click(function () { // 移除当前被删除文件的URL var fileDelUrl = $(this).attr("fileurl"); var uploadArray = $("#UploadControl_fileUploadUrl").val().split(','); for (var i = 0; i < uploadArray.length; i++) { if (uploadArray[i] == fileDelUrl) { uploadArray.splice(i, 1); } } // 将保存上传文件URL的input重赋值 $("#UploadControl_fileUploadUrl").val(uploadArray); // 移除删除文件的li $(this).parent().remove(); // 判断ul是否为空 var uploadFileLiLen = $("#JUploadFileImg").find("li").length; var uploadPicLiLen = $("#JUploadImgs").find("li").length; if (uploadFileLiLen == 0 && uploadPicLiLen == 0) { $("#JShowAll").hide(); } }); }); // 当上传出错时触发 uploader.bind('Error', function (uploader, errObject) { //每个事件监听函数都会传入一些很有用的参数, //我们可以利用这些参数提供的信息来做比如更新UI,提示上传进度等操作 }); //最后给"开始上传"按钮注册事件 document.getElementById('JToUpload').onclick = function () { //调用实例对象的start()方法开始上传文件,当然你也可以在其他地方调用该方法 uploader.start(); } // 删除待上传队列中的文件 $("#JShowFileImg,#JShowImgs").on('click', '.del_WaitUpload', function (e) { // 获取想要删除的上传队列文件的ID var FileId = $(this).attr("FileId"); // 根据文件ID获取想要删除的文件 var file = uploader.getFile(FileId); // 从uploader对象中移除目标文件 uploader.removeFile(file); // 同时移除展示文件的li $(this).parent().remove(); // 获取待上传文件的数量 var waitUploadFileLiLen = $("#JShowFileImg").find('li').length; var waitUploadPicLiLen = $("#JShowImgs").find("li").length; if (waitUploadFileLiLen == 0 && waitUploadPicLiLen == 0) { $(".J-show-the-name").hide(); } // 重新计算未上传的文件展示宽度 Funs.setImgWidth($("#JShowImgs li")); }); // 上传进度条显示 function uploadProcess(t) { // 展示进度条 $(".ProgressBar").show(); // 进度条百分比框 var jindutiao = document.getElementById("progress"); jindutiao.style.width = t + "%"; jindutiao.innerHTML = jindutiao.style.width; } // 清理进度条框文本并隐藏进度条 function clearProcess() { var jindutiao = document.getElementById("progress"); jindutiao.style.width = "0%"; jindutiao.innerHTML = "0%"; // 隐藏进度条 $(".ProgressBar").hide(); } // 图片预览 function previewImage(file, callback) { if (!file || !/image\//.test(file.type)) return; if (file.type == 'image/gif') { var fr = new mOxie.FileReader(); fr.onload = function () { callback(fr.result); fr.destroy(); fr = null; } fr.readAsDataURL(file.getSource()); } else { var img = new moxie.image.Image(); img.load(file.getSource()); img.onload = function () { img.downsize(300, 300);// 压缩要预览的图片,宽300,高300 var imgsrc = img.type == 'image/jpeg' ? img.getAsDataURL('image/jpeg', 90) : img.getAsDataURL(); // 得到图片src,base64编码的数据 callback && callback(imgsrc); // callback传入的参数为预览图片的url img.destroy(); img = null; }; } } </script>
接下来是我后台的代码,如果只是想了解plupload控件的朋友就可以不用看下去了,这些算是我自己对自己的一个总结:
这是我handler的部分,主要是接收控件传进来的文件并传入文件上传方法及返回上传结果:
using EPC.Components.FileManage; using EPC.FileManage.Entity; using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Script.Serialization; namespace EPC.FileManager.Handler { /// <summary> /// UploadHandler 的摘要说明 /// </summary> public class UploadHandler : IHttpHandler { /// <summary> /// 文件上传 /// <author>Asa</author> /// <createDate>2019-05-01</createDate> /// </summary> /// <param name="context">http上下文对象</param> public void ProcessRequest(HttpContext context) { context.Response.ContentType = "text/plain"; context.Response.Clear(); // 声明一个用于序列化的对象 JavaScriptSerializer javaScriptSerializer = new JavaScriptSerializer(); // 判断待上传文件是否为空 if (context.Request.Files.Count > 0) { for (int i = 0; i < context.Request.Files.Count; i++) { // 接收待上传的文件对象 HttpPostedFile file = HttpContext.Current.Request.Files[i]; // 调用上传文件的方法 EPC_UploadResponse epc_UploadResponse = EPC_FileManage.UploadFile(file); // 返回上传结果 HttpContext.Current.Response.Write(javaScriptSerializer.Serialize(epc_UploadResponse)); } } } public bool IsReusable { get { return false; } } } }
这一块是我上传方法的部分:
using EPC.Common; using EPC.FileManage.Entity; using System; using System.Configuration; using System.IO; using System.Linq; using System.Web; using System.Web.Script.Serialization; namespace EPC.Components.FileManage { /// <summary> /// EPC文件管理类 /// <author>Asa</author> /// <createDate>2019-05-15</createDate> /// </summary> public class EPC_FileManage { public static EPC_UploadResponse UploadFile(HttpPostedFile file) { #region 读取文件上传相关配置,定义文件上传所需变量--BEGIN // 定义一个变量接收待上传文件名称 string fileName = string.Empty; // 定义一个变量接收待上传文件类型 string fileType = string.Empty; // 读取允许上传的文件类型配置 string allowedFileType = ConfigurationManager.AppSettings["allowedFileType"]; // 定义一个数组接收允许上传的文件类型 string[] allowedFileTypeArray = null; // 读取允许上传的文件大小(KB) string allowedFileSizeStr = ConfigurationManager.AppSettings["allowedFileSize"]; // 定义一个变量接收转换为int类型的allowedFileSize int allowedFileSizeInt = 0; // 读取API请求地址前缀 string apiUrlPrefix = ConfigurationManager.AppSettings["apiUrlPrefix"]; // 定义一个变量拼接完整的接口请求地址 string apiFullUrl = string.Empty; // 创建一个上传结果响应类对象 EPC_UploadResponse epcUploadResponse = new EPC_UploadResponse(); // 定义一个用于反序列化的对象 JavaScriptSerializer javaScriptSerializer = new JavaScriptSerializer(); #endregion 读取文件上传相关配置,定义文件上传所需变量--END #region 判断文件上传相关配置是否合法及上传文件是否为空--BEGIN // 判断允许上传的文件类型配置是否为空 if (string.IsNullOrEmpty(allowedFileType)) { epcUploadResponse.StatusCode = 001; epcUploadResponse.Message = "上传失败:缺少允许上传的文件类型配置"; return epcUploadResponse; } // 判断允许上传的文件大小配置是否为空 if (string.IsNullOrEmpty(allowedFileSizeStr)) { epcUploadResponse.StatusCode = 001; epcUploadResponse.Message = "上传失败:缺少允许上传的文件大小配置"; return epcUploadResponse; } // 判断API请求地址前缀配置是否为空 if (string.IsNullOrEmpty(apiUrlPrefix)) { epcUploadResponse.StatusCode = 001; epcUploadResponse.Message = "上传失败:缺少请求API的地址前缀配置"; return epcUploadResponse; } // 判断待上传文件是否为空。 if (file == null) { epcUploadResponse.StatusCode = 001; epcUploadResponse.Message = "上传失败:缺少文件"; return epcUploadResponse; } #endregion 判断文件上传相关配置是否合法及上传文件是否为空--END #region 判断文件格式和大小是否符合规则--BEGIN // 接收允许上传的文件类型 try { allowedFileTypeArray = allowedFileType.Split(','); } catch { epcUploadResponse.StatusCode = 001; epcUploadResponse.Message = "上传失败:允许上传文件类型配置不合法"; return epcUploadResponse; } // 接收允许上传的文件大小 try { allowedFileSizeInt = Convert.ToInt32(allowedFileSizeStr); } catch { epcUploadResponse.StatusCode = 001; epcUploadResponse.Message = "上传失败:允许上传文件大小配置不合法"; return epcUploadResponse; } // 获取待上传文件的文件名 fileName = file.FileName; // 获取待上传文件的类型 fileType = Path.GetExtension(fileName); // 判断文件类型是否合法 if (!allowedFileTypeArray.Contains(fileType)) { epcUploadResponse.StatusCode = 001; epcUploadResponse.Message = "上传失败:‘" + fileType + "’文件格式不合法" + allowedFileTypeArray + ""; return epcUploadResponse; } // 判断允许上传的文件大小是否超过默认最大值 if ((allowedFileSizeInt / 1024) <= 200) { if ((file.ContentLength / 1024) > allowedFileSizeInt) { epcUploadResponse.StatusCode = 001; epcUploadResponse.Message = "上传失败:‘" + (file.ContentLength / 1024) + "kb’文件大小不合法"; return epcUploadResponse; } } else { if ((file.ContentLength / 1024 / 1024) > 200) { epcUploadResponse.StatusCode = 001; epcUploadResponse.Message = "上传失败:‘" + (file.ContentLength / 1024 / 1024) + "kb’文件大小不合法"; return epcUploadResponse; } } #endregion 判断文件格式和大小是否符合规则--END #region API接口方式上传 try { // API请求地址 apiFullUrl = apiUrlPrefix + "/" + "API/UploadFile/Save"; // 待上传文件流 Stream waitUploadStream = file.InputStream; // 待压缩字节 byte[] waitCompressByte = Utiles.StreamToBytes(waitUploadStream); // 已压缩字节 byte[] compressedByte = Utiles.CompressBytes(waitCompressByte); // 待上传文件流 waitUploadStream = Utiles.BytesToStream(compressedByte); // 接收文件上传返回结果 string uploadResponse = Utiles.HttpPostUpload(apiFullUrl, file.FileName, waitUploadStream); // 反序列化响应结果并赋值给文件上传响应实体 epcUploadResponse = javaScriptSerializer.Deserialize<EPC_UploadResponse>(uploadResponse); } catch (Exception ex) { epcUploadResponse.StatusCode = 002; epcUploadResponse.Message = "文件上传失败:无法连接到服务器"; return epcUploadResponse; } #endregion // 返回上传结果响应类 return epcUploadResponse; } } }
这部分是我的公共方法代码:
using System; using System.IO; using System.IO.Compression; using System.Net; using System.Text; namespace EPC.Common { /// <summary> /// 文件管理系统工具类 /// <author>Asa</author> /// <createDate>20190507</createDate> /// </summary> public class Utiles { /// <summary> /// 文件流转字节 /// </summary> /// <author>Asa</author> /// <createDate>20190507</createDate> /// <param name="stream">文件流</param> /// <returns></returns> public static byte[] StreamToBytes(Stream stream) { byte[] array = new byte[stream.Length]; stream.Seek(0L, SeekOrigin.Begin); stream.Read(array, 0, array.Length); stream.Close(); return array; } /// <summary> /// 将字节转为文件流 /// </summary> /// <author>Asa</author> /// <createDate>20190507</createDate> /// <param name="stream">字节</param> /// <returns></returns> public static Stream BytesToStream(byte[] bytes) { return new MemoryStream(bytes); } /// <summary> /// 模拟POST提交上传请求 /// <author>Asa</author> /// <createDate>20190507</createDate> /// </summary> /// <param name="url">自定义请求url</param> /// <param name="fileName">上传的文件名</param> /// <param name="stream">流</param> /// <param name="timeOut">超时时间[暂未使用]</param> /// <returns>返回字符串类型</returns> public static string HttpPostUpload(string url, string fileName, Stream stream, int timeOut = 0) { // 定义一个相应内容对象 string responseContent; // 定义一个内存流对象(用于接收待上传文件) MemoryStream memStream = new MemoryStream(); // 定义一个发送自定义post请求的对象 HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url); // 边界符 string boundary = "----WebKitFormBoundaryut99VQ34SOB8NU0X\r\n"; // 边界符 byte[] beginBoundary = Encoding.ASCII.GetBytes("--" + boundary); // 最后的结束符 byte[] endBoundary = Encoding.ASCII.GetBytes("------WebKitFormBoundaryut99VQ34SOB8NU0X--\r\n"); // 设置属性 webRequest.Method = "POST"; webRequest.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"; webRequest.ContentType = "multipart/form-data; boundary=" + boundary; // 开始时间参数(你可以把你需要的参数写在请求头里面传进接口) string dateNow = DateTime.Now.ToString("yyyyMMdd"); webRequest.Headers.Add("dateNow", dateNow); // 写入文件 const string filePartHeader = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\";\r\n" + "datenow=\"{2}\"\r\n" + "Content-Type: application/octet-stream\r\n\r\n"; string header = string.Format(filePartHeader, "file", fileName, dateNow); byte[] headerbytes = Encoding.UTF8.GetBytes(header); memStream.Write(beginBoundary, 0, beginBoundary.Length); memStream.Write(headerbytes, 0, headerbytes.Length); // 将文件流转换为字节 byte[] temp = StreamToBytes(stream); // 将字节写入内存流 memStream.Write(temp, 0, temp.Length); byte[] tt = Encoding.UTF8.GetBytes("\r\n"); memStream.Write(tt, 0, tt.Length); // Key-Value数据 var stringKeyHeader = "--" + boundary + "\r\nContent-Disposition: form-data; name=\"{0}\"" + "\r\n\r\n{1}\r\n"; // 写入最后的结束边界符 memStream.Write(endBoundary, 0, endBoundary.Length); Stream requestStream = webRequest.GetRequestStream(); StreamWriter myStreamWriter = new StreamWriter(requestStream, Encoding.GetEncoding("utf-8")); memStream.Position = 0; byte[] tempBuffer = new byte[memStream.Length]; memStream.Read(tempBuffer, 0, tempBuffer.Length); memStream.Close(); requestStream.Write(tempBuffer, 0, tempBuffer.Length); requestStream.Close(); HttpWebResponse httpWebResponse = (HttpWebResponse)webRequest.GetResponse(); using (StreamReader httpStreamReader = new StreamReader(httpWebResponse.GetResponseStream(), Encoding.GetEncoding("utf-8"))) { responseContent = httpStreamReader.ReadToEnd(); } httpWebResponse.Close(); webRequest.Abort(); return responseContent; } /// <summary> /// 压缩字节 /// <author>黄磊</author> /// <createDate>2019-04-11</createDate> /// </summary> /// <param name="bytes">待压缩字节</param> /// <returns>压缩字节</returns> public static byte[] CompressBytes(byte[] bytes) { using (MemoryStream compressStream = new MemoryStream()) { using (var zipStream = new GZipStream(compressStream, CompressionMode.Compress)) zipStream.Write(bytes, 0, bytes.Length); return compressStream.ToArray(); } } /// <summary> /// 解压缩字节 /// </summary> /// <param name="bytes">待解压缩字节</param> /// <returns>解压缩字节</returns> public static byte[] DeCompressBytes(byte[] bytes) { using (var compressStream = new MemoryStream(bytes)) { using (var zipStream = new GZipStream(compressStream, CompressionMode.Decompress)) { using (var resultStream = new MemoryStream()) { zipStream.CopyTo(resultStream); return resultStream.ToArray(); } } } } } }
这部分是我接口的代码(WebApi):
using APIs.EPC.FileManage.WebAPI.Entity.Entity; using EPC.Common; using EPC.FileManage.BLL.FileInfoManage; using EPC.FileManage.Entity; using PL.Base; using System; using System.Configuration; using System.IO; using System.Net; using System.Net.Http; using System.Text; using System.Web; using System.Web.Http; using System.Web.Script.Serialization; namespace EPC.FileManage.Api.Controllers { /// <summary> /// 文件上传接口 /// <author>Asa</author> /// <createDate>2019-05-11</createDate> /// </summary> public class UploadFileController : BaseController { /// <summary> /// 接收上传请求接口 /// <author>Asa</author> /// <createDate>2018/09/11</createDate> /// </summary> /// <returns>返回详细的图片带访问前缀的URL</returns> [HttpPost] public HttpResponseMessage Save() { #region 读取与设置上传文件需要的配置 // 返回文件保存的地址 string returnSaveUrl = string.Empty; // 设置文件上传的日期(用于创建保存地址使用) string fileUploadDate = DateTime.Now.ToString("yyyyMMdd"); // 读取文件访问地址前缀 string fileUrlPrefix = ConfigurationManager.AppSettings["fileUrlPrefix"]; // 读取文件保存的文件夹配置 string fileSaveFolder = ConfigurationManager.AppSettings["fileSaveFolder"]; // 获取待上传文件文件名 string oldFileName = string.Empty; // 获取待上传文件拓展名 string extensionName = string.Empty; // 文件重命名 string fileNewName = string.Empty; // 设置文件保存路径 string fileSavePath = HttpContext.Current.Server.MapPath("~\\" + fileSaveFolder + "\\" + fileUploadDate + "\\"); // 定义一个默认的图片类型数组 //string[] picTypeArray = { ".png", ".jpg", ".jpeg" }; // 定义一个HTTP响应对象 HttpResponseMessage httpResponseMessage = new HttpResponseMessage(); // 定义一个上传结果响应实体 EPC_UploadResponse epc_UploadResponse = new EPC_UploadResponse(); // 定义一个用于序列化的对象 JavaScriptSerializer javaScriptSerializer = new JavaScriptSerializer(); // 判断存放上传文件的文件夹的配置是否为空 if (string.IsNullOrEmpty(fileSaveFolder)) { epc_UploadResponse.StatusCode = 001; epc_UploadResponse.Message = "缺少存放上传文件的文件夹配置"; httpResponseMessage.StatusCode = HttpStatusCode.OK; httpResponseMessage.Content = new StringContent(javaScriptSerializer.Serialize(epc_UploadResponse)); return httpResponseMessage; } // 判断文件访问地址前缀配置是否为空 if (string.IsNullOrEmpty(fileUrlPrefix)) { epc_UploadResponse.StatusCode = 001; epc_UploadResponse.Message = "缺少文件访问地址前缀配置"; httpResponseMessage.StatusCode = HttpStatusCode.OK; httpResponseMessage.Content = new StringContent(javaScriptSerializer.Serialize(epc_UploadResponse), Encoding.UTF8, "json"); return httpResponseMessage; } #endregion 读取与设置上传文件需要的配置 #region 保存文件到指定文件夹 // 判断保存文件的地址是否存在,如果不存在就创建该地址 if (!Directory.Exists(fileSavePath)) Directory.CreateDirectory(fileSavePath); // 接收要上传的文件 HttpFileCollection files = HttpContext.Current.Request.Files; var dateNow = HttpContext.Current.Request.Headers["dateNow"]; // 遍历文件集合,上传文件 foreach (string key in files.AllKeys) { try { // 定义一个上传文件相关信息实体类对象 EPC_UploadFileInfo epc_UploadFileInfo = new EPC_UploadFileInfo(); // 读取待上传的文件 HttpPostedFile waitUploadFile = files[key]; // 获取待上传文件的文件名 oldFileName = waitUploadFile.FileName; // 获取待上传文件的拓展名 extensionName = Path.GetExtension(oldFileName); // 待上传文件流 Stream waitUploadStream = waitUploadFile.InputStream; // 待解压缩字节 byte[] waitDeCompressByte = Utiles.StreamToBytes(waitUploadStream); // 已解压缩字节 byte[] DeCompressedByte = Utiles.DeCompressBytes(waitDeCompressByte); // 文件重命名 fileNewName = DateTime.Now.ToString("yyyyMMddHHmmssfff") + extensionName; // 执行保存图片到服务器的操作 File.WriteAllBytes(fileSavePath + fileNewName, DeCompressedByte); // 返回文件保存路径 returnSaveUrl = (fileUrlPrefix + "/" + fileSaveFolder + "/" + fileUploadDate + "/" + fileNewName); // 响应类赋值 epc_UploadResponse.StatusCode = 001; epc_UploadResponse.Message = "文件上传成功"; epc_UploadResponse.FileName = oldFileName; epc_UploadResponse.FileType = extensionName; epc_UploadResponse.FileUrl = returnSaveUrl; httpResponseMessage.StatusCode = HttpStatusCode.OK; httpResponseMessage.Content = new StringContent(javaScriptSerializer.Serialize(epc_UploadResponse)); } catch (Exception ex) { // 将文件保存失败错误写入日志 Log.Write("文件保存失败:" + ex.Message, "文件保存失败"); // 组装文件上传结果并返回 epc_UploadResponse.StatusCode = 002; epc_UploadResponse.Message = "文件保存失败"; httpResponseMessage.StatusCode = HttpStatusCode.OK; httpResponseMessage.Content = new StringContent(javaScriptSerializer.Serialize(epc_UploadResponse)); return httpResponseMessage; } } #endregion 保存文件到指定文件夹 // 返回文件上传响应结果 return httpResponseMessage; } } }
这是我的响应实体类:
namespace EPC.FileManage.Entity { /// <summary> /// 文件上传响应实体 /// <author>Asa</author> /// <createDate>2019-0515</createDate> /// </summary> public class EPC_UploadResponse { /// <summary> /// 状态码 /// </summary> public int StatusCode { get; set; } /// <summary> /// 上传结果提示信息 /// </summary> public string Message { get; set; } /// <summary> /// 逻辑文件名 /// </summary> public string FileName { get; set; } /// <summary> /// 文件类型 /// </summary> public string FileType { get; set; } /// <summary> /// 文件地址 /// </summary> public string FileUrl { get; set; } } }
这是最后运行的效果图:
点击开始上传按钮后:
上传之后还可以继续选择文件上传:
好了,一个完整的通过接口实现文件上传的功能就结束了,不过我发现plupload控件无法选择txt,docx文件,不知道是本身的bug还是我哪里写的有问题,正在研究中,有知道的小伙伴也可以告诉我一下,谢谢,感谢耐心看完的小伙伴们....
忘了附上需要的js和css了,抱歉,hahaha...
试了一下,js和css文件目前无法上传,如果有需要的话可以找我要,也可以自己去下载,不过展示界面就只能大家自己写了