
最近一段时间都在使用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文件目前无法上传,如果有需要的话可以找我要,也可以自己去下载,不过展示界面就只能大家自己写了


剑轩