Asp.Net Framework webapi2 文件上传与下载 前端界面采用Ajax的方式执行
一、项目结构
1.App_Start配置了跨域访问,以免请求时候因跨域问题不能提交。具体的跨域配置方式如下,了解的朋友请自行略过。
跨域配置:NewGet安装dll Microsofg.AspNet.Cors
然后在App_Start 文件夹下的WebApiConfig.cs中写入跨域配置代码。
1 public static class WebApiConfig 2 { 3 public static void Register(HttpConfiguration config) 4 { 5 // Web API configuration and services 6 7 // Web API routes 8 config.MapHttpAttributeRoutes(); 9 10 // Web API configuration and services 11 //跨域配置 //need reference from nuget 12 config.EnableCors(new EnableCorsAttribute("*", "*", "*")); 13 14 config.Routes.MapHttpRoute( 15 name: "DefaultApi", 16 routeTemplate: "api/{controller}/{id}", 17 defaults: new { id = RouteParameter.Optional } 18 ); 19 20 //if config the global filter input there need not write the attributes 21 //config.Filters.Add(new App.WebApi.Filters.ExceptionAttribute_DG()); 22 } 23 }
跨域就算完成了,请自行测试。
2.新建两个控制器,一个PicturesController.cs,一个FilesController.cs当然图片也是文件,这里图片和文件以不同的方式处理的,因为图片的方式文件上传没有成功,所以另寻他路,如果在座的有更好的方式,请不吝赐教!
二、项目代码
1.我们先说图片上传、下载控制器接口,这里其实没什么好说的,就一个Get获取文件,参数是文件全名;Post上传文件;直接上代码。
1 using QX_Frame.App.WebApi; 2 using QX_Frame.FilesCenter.Helper; 3 using QX_Frame.Helper_DG; 4 using QX_Frame.Helper_DG.Extends; 5 using System; 6 using System.Collections.Generic; 7 using System.Diagnostics; 8 using System.IO; 9 using System.Linq; 10 using System.Net; 11 using System.Net.Http; 12 using System.Net.Http.Headers; 13 using System.Text; 14 using System.Threading.Tasks; 15 using System.Web.Http; 16 17 /** 18 * author:qixiao 19 * create:2017-5-26 16:54:46 20 * */ 21 namespace QX_Frame.FilesCenter.Controllers 22 { 23 public class PicturesController : WebApiControllerBase 24 { 25 //Get : api/Pictures 26 public HttpResponseMessage Get(string fileName) 27 { 28 HttpResponseMessage result = null; 29 30 DirectoryInfo directoryInfo = new DirectoryInfo(IO_Helper_DG.RootPath_MVC + @"Files/Pictures"); 31 FileInfo foundFileInfo = directoryInfo.GetFiles().Where(x => x.Name == fileName).FirstOrDefault(); 32 if (foundFileInfo != null) 33 { 34 FileStream fs = new FileStream(foundFileInfo.FullName, FileMode.Open); 35 36 result = new HttpResponseMessage(HttpStatusCode.OK); 37 result.Content = new StreamContent(fs); 38 result.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream"); 39 result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment"); 40 result.Content.Headers.ContentDisposition.FileName = foundFileInfo.Name; 41 } 42 else 43 { 44 result = new HttpResponseMessage(HttpStatusCode.NotFound); 45 } 46 47 return result; 48 } 49 50 51 //POST : api/Pictures 52 public async TaskPost() 53 { 54 if (!Request.Content.IsMimeMultipartContent()) 55 { 56 throw new Exception_DG("unsupported media type", 2005); 57 } 58 string root = IO_Helper_DG.RootPath_MVC; 59 60 IO_Helper_DG.CreateDirectoryIfNotExist(root + "/temp"); 61 62 var provider = new MultipartFormDataStreamProvider(root + "/temp"); 63 64 // Read the form data. 65 await Request.Content.ReadAsMultipartAsync(provider); 66 67 List<string> fileNameList = new List<string>(); 68 69 StringBuilder sb = new StringBuilder(); 70 71 long fileTotalSize = 0; 72 73 int fileIndex = 1; 74 75 // This illustrates how to get the file names. 76 foreach (MultipartFileData file in provider.FileData) 77 { 78 //new folder 79 string newRoot = root + @"Files/Pictures"; 80 81 IO_Helper_DG.CreateDirectoryIfNotExist(newRoot); 82 83 if (File.Exists(file.LocalFileName)) 84 { 85 //new fileName 86 string fileName = file.Headers.ContentDisposition.FileName.Substring(1, file.Headers.ContentDisposition.FileName.Length - 2); 87 88 string newFileName = Guid.NewGuid() + "." + fileName.Split('.')[1]; 89 90 string newFullFileName = newRoot + "/" + newFileName; 91 92 fileNameList.Add($"Files/Pictures/{newFileName}"); 93 94 FileInfo fileInfo = new FileInfo(file.LocalFileName); 95 96 fileTotalSize += fileInfo.Length; 97 98 sb.Append($" #{fileIndex} Uploaded file: {newFileName} ({ fileInfo.Length} bytes)"); 99 100 fileIndex++; 101 102 File.Move(file.LocalFileName, newFullFileName); 103 104 Trace.WriteLine("1 file copied , filePath=" + newFullFileName); 105 } 106 } 107 108 return Json(Return_Helper.Success_Msg_Data_DCount_HttpCode($"{fileNameList.Count} file(s) /{fileTotalSize} bytes uploaded successfully! Details -> {sb.ToString()}", fileNameList, fileNameList.Count)); 109 } 110 } 111 }
里面可能有部分代码在Helper帮助类里面写的,其实也仅仅是获取服务器根路径和如果判断文件夹不存在则创建目录,这两个代码的实现如下:
1 public static string RootPath_MVC 2 { 3 get { return System.Web.HttpContext.Current.Server.MapPath("~"); } 4 }
1 //create Directory 2 public static bool CreateDirectoryIfNotExist(string filePath) 3 { 4 if (!Directory.Exists(filePath)) 5 { 6 Directory.CreateDirectory(filePath); 7 } 8 return true; 9 }
2.文件上传下载接口和图片大同小异。
1 using QX_Frame.App.WebApi; 2 using QX_Frame.FilesCenter.Helper; 3 using QX_Frame.Helper_DG; 4 using System.Collections.Generic; 5 using System.Diagnostics; 6 using System.IO; 7 using System.Linq; 8 using System.Net; 9 using System.Net.Http; 10 using System.Net.Http.Headers; 11 using System.Text; 12 using System.Threading.Tasks; 13 using System.Web; 14 using System.Web.Http; 15 16 /** 17 * author:qixiao 18 * create:2017-5-26 16:54:46 19 * */ 20 namespace QX_Frame.FilesCenter.Controllers 21 { 22 public class FilesController : WebApiControllerBase 23 { 24 //Get : api/Files 25 public HttpResponseMessage Get(string fileName) 26 { 27 HttpResponseMessage result = null; 28 29 DirectoryInfo directoryInfo = new DirectoryInfo(IO_Helper_DG.RootPath_MVC + @"Files/Files"); 30 FileInfo foundFileInfo = directoryInfo.GetFiles().Where(x => x.Name == fileName).FirstOrDefault(); 31 if (foundFileInfo != null) 32 { 33 FileStream fs = new FileStream(foundFileInfo.FullName, FileMode.Open); 34 35 result = new HttpResponseMessage(HttpStatusCode.OK); 36 result.Content = new StreamContent(fs); 37 result.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream"); 38 result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment"); 39 result.Content.Headers.ContentDisposition.FileName = foundFileInfo.Name; 40 } 41 else 42 { 43 result = new HttpResponseMessage(HttpStatusCode.NotFound); 44 } 45 46 return result; 47 } 48 49 //POST : api/Files 50 public async TaskPost() 51 { 52 //get server root physical path 53 string root = IO_Helper_DG.RootPath_MVC; 54 55 //new folder 56 string newRoot = root + @"Files/Files/"; 57 //check path is exist if not create it 58 IO_Helper_DG.CreateDirectoryIfNotExist(newRoot); 59 60 List<string> fileNameList = new List<string>(); 61 62 StringBuilder sb = new StringBuilder(); 63 64 long fileTotalSize = 0; 65 66 int fileIndex = 1; 67 68 //get files from request 69 HttpFileCollection files = HttpContext.Current.Request.Files; 70 71 await Task.Run(() => 72 { 73 foreach (var f in files.AllKeys) 74 { 75 HttpPostedFile file = files[f]; 76 if (!string.IsNullOrEmpty(file.FileName)) 77 { 78 79 string fileLocalFullName = newRoot + file.FileName; 80 81 file.SaveAs(fileLocalFullName); 82 83 fileNameList.Add($"Files/Files/{file.FileName}"); 84 85 FileInfo fileInfo = new FileInfo(fileLocalFullName); 86 87 fileTotalSize += fileInfo.Length; 88 89 sb.Append($" #{fileIndex} Uploaded file: {file.FileName} ({ fileInfo.Length} bytes)"); 90 91 fileIndex++; 92 93 Trace.WriteLine("1 file copied , filePath=" + fileLocalFullName); 94 } 95 } 96 }); 97 98 99 return Json(Return_Helper.Success_Msg_Data_DCount_HttpCode($"{fileNameList.Count} file(s) /{fileTotalSize} bytes uploaded successfully! Details -> {sb.ToString()}", fileNameList, fileNameList.Count)); 100 } 101 } 102 }
实现了上述两个控制器代码以后,我们需要前端代码来调试对接,代码如下所示。
1 doctype> 2 3 <head> 4 <script src="jquery-3.2.0.min.js">script> 5 6 7 <script> 8 $(document).ready(function () { 9 var appDomain = "http://localhost:3997/"; 10 11 12 $("#btn_fileUpload").click(function () { 13 14 /** 15 * 用ajax方式上传文件 ----------- 16 * */ 17 //-------asp.net webapi fileUpload 18 // 19 var formData = new FormData($("#uploadForm")[0]); 20 $.ajax({ 21 url: appDomain + 'api/Files', 22 type: 'POST', 23 data: formData, 24 async: false, 25 cache: false, 26 contentType: false, 27 processData: false, 28 success: function (data) { 29 console.log(JSON.stringify(data)); 30 }, 31 error: function (data) { 32 console.log(JSON.stringify(data)); 33 } 34 }); 35 //----end asp.net webapi fileUpload 36 37 //----.net core webapi fileUpload 38 // var fileUpload = $("#files").get(0); 39 // var files = fileUpload.files; 40 // var data = new FormData(); 41 // for (var i = 0; i < files.length; i++) { 42 // data.append(files[i].name, files[i]); 43 // } 44 // $.ajax({ 45 // type: "POST", 46 // url: appDomain+'api/Files', 47 // contentType: false, 48 // processData: false, 49 // data: data, 50 // success: function (data) { 51 // console.log(JSON.stringify(data)); 52 // }, 53 // error: function () { 54 // console.log(JSON.stringify(data)); 55 // } 56 // }); 57 //--------end net core webapi fileUpload 58 59 /** 60 * ajaxfileupload.js 方式上传文件 61 * */ 62 // $.ajaxFileUpload({ 63 // type: 'post', 64 // url: appDomain + 'api/Files', 65 // secureuri: false, 66 // fileElementId: 'files', 67 // success: function (data) { 68 // console.log(JSON.stringify(data)); 69 // }, 70 // error: function () { 71 // console.log(JSON.stringify(data)); 72 // } 73 // }); 74 75 }); 76 //end click 77 78 79 }) 80 script> 81 head> 82 <title>title> 83 84 <body> 85 <article> 86 <header> 87 <h2>article-formh2> 88 header> 89 <p> 90 <form action="/" method="post" id="uploadForm" enctype="multipart/form-data"> 91 <input type="file" id="files" name="files" placeholder="file" multiple>file-multiple属性可以选择多项<br><br> 92 <input type="button" id="btn_fileUpload" value="fileUpload"> 93 form> 94 p> 95 article> 96 body>
至此,我们的功能已全部实现,下面我们来测试一下:
可见,文件上传成功,按预期格式返回!
下面我们测试单图片上传->
然后我们按返回的地址进行访问图片地址。
发现并无任何压力!
下面测试多图片上传->
完美~
至此,我们已经实现了WebApi2文件和图片上传,下载的全部功能。
这里需要注意一下Web.config的配置上传文件支持的总大小,我这里配置的是最大支持的文件大小为1MB
1 <system.webServer> 2 <handlers> 3 <remove name="ExtensionlessUrlHandler-Integrated-4.0" /> 4 <remove name="OPTIONSVerbHandler" /> 5 <remove name="TRACEVerbHandler" /> 6 <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" /> 7 handlers> 8 <security> 9 <requestFiltering> 10 <requestLimits maxAllowedContentLength="1048576" /> 11 requestFiltering> 12 security> 13 system.webServer>
OK,共同学习~
该项目已迁移成文件中心(专用来处理文件上传下载的接口),GitHub地址:https://github.com/dong666/QX_Frame.FilesCenter