Creating a file Management interface for a website or other Web application (WEBAPI) Chapter III, "Multi-File Upload + database-assisted storage"
========================================================
Qiujuer
Blog: Blog.csdn.net/qiujuer
Website: www.qiujuer.net
Open Source Library: genius-android
Reprint Please specify source: http://blog.csdn.net/qiujuer/article/details/41721165
========================================================
History
[WebApi] Tinkering with a resource Manager--File download
[WebApi] Tinkering with a resource manager-multiple file uploads
In the preface
In the previous chapter, we explained how to implement file upload, which seems to be poorly managed after uploading to the server, and it doesn't seem to know where to start every time a file is downloaded.
In this chapter, we will explain how to upload and store files in conjunction with the data to ensure that the files are stored securely and easily enough, and that the same file is not saved repeatedly.
Brief analysis
- When we want to, how can a file be saved to a database so that it has some security ? This simple, easiest way is to get rid of the suffix name . It's a lot different than encryption, but if someone gets what they want to know, it's going to take a little thought.
- The additional burden is added to meet the above requirements, such as that the file is not suffixed, so what do we do when we need to download the file? At this point we need to record the basic information of the document .
- We know that in the general upload file controls are stored separately according to the date of the year; but have you ever thought of repeating the same file ? For such a problem seems to be not on the other plug-ins, not to do, but not to do so! We have to do it now. So we need to have this function, so how to uniquely identify a file? The simplest way is to MD5.
- In response to the above questions; it seems that we all have ideas, so now we should know that the database is not used to store files, but rather to store the files stored information, to identify the management file .
Codetime
All right, here we go, the code module.
Changes
Let's take a look at the changes we've made in this time, of course, relative to the previous version.
As can be seen, a total of 6 files were changed, including:Web, Upload, resouce, Resouceapi; add:hashutils, Webresoucecontext.
ModelResource.cs
Using system;using system.componentmodel.dataannotations;namespace webresource.models{//<summary>///File storage Letter Data Sheet//</summary> public class Resource {///<summary>//Id used to uniquely identify///store Log text Piece MD5///MD5 value of file name + file size in the continuation of the breakpoint///</summary> [Key] public string Id {get; set;} <summary>///File name///</summary> [Required] public string name {get; set ; }///<summary>///File Size///</summary> [Required] public long size {get; Set }///<summary>///The current storage location///breakpoint continued to determine whether the transmission is complete///</summary> [Required] Public long Cursor {get; set;} <summary>///file type///</summary> [Required] public string type {get; set;} <summary>////Storage Folder///</summary> [Required] public string Folder {get; set;} <summary>//////</summary> [Required] public int Clicks {get; set;} <summary>///Storage Date///</summary> [Required] public DateTime Published { Get Set } }}
This is the database table structure modified on the basis of the previous version; It seems to me that the stored information of a file should contain the above information;Breakpoint ContinuationOfCursorThe property is temporarily virtual and is not actually used; This will explain in detail how to add a breakpoint continuation in a later version. Basic information about the file please ask for a better plan.
HashUtils.cs
Using system;using system.io;using system.security.cryptography;namespace webresource.models{public class HashUtils {//<summary>//md5-format [uppercase]///</summary>/<param name= "FileStream "> File filestream</param>///<returns>MD5Hash</returns> public static string Getmd5hash (F Ilestream FileStream) {try {MD5 md5provider = new MD5CryptoServiceProvider () ; byte[] buffer = Md5provider.computehash (FileStream); Md5provider.clear (); return bitconverter.tostring (buffer). Replace ("-", "" "); } catch {return null;} }///<summary>///Get the md5-format of the string [uppercase]///</summary>/<param name= "str" > character String </param>///<returns>MD5Hash</returns> public static string Getmd5hash (String str) {try { MD5 Md5provider = new MD5CryptoServiceProvider (); byte[] buffer = Md5provider.computehash (System.Text.Encoding.UTF8.GetBytes (str)); Md5provider.clear (); return bitconverter.tostring (buffer). Replace ("-", "" "); } catch {return null;} }///<summary>///Calculate the md5-format of byte array [uppercase]///</summary>//<param name= "bytes" & gt;byte[]</param>//<returns>MD5Hash</returns> public static string Getmd5hash (byte[) by TES) {try {MD5 md5provider = new MD5CryptoServiceProvider (); byte[] buffer = md5provider.computehash (bytes); Md5provider.clear (); return bitconverter.tostring (buffer). Replace ("-", "" "); } catch {return null;} } }}
As the name implies, this class is used to calculate
MD5Of course, the actual use will only use the 3rd method, the first two are written together may be used later.
WebResourceContext.cs
Using System.data.entity;namespace webresource.models{public class Webresourcecontext:dbcontext { Public Webresourcecontext (): Base ("Name=webresourcecontext") { } public system.data.entity.dbset< Webresource.models.resource> Resources {get; set;}}}
This class is simple and straightforward; The EF DB should be understood at a glance; This class is the class used for data table queries; Of course, EF is used.
It specifies "Name=webresourcecontext", which is used to correspond to the database connection fields in the configuration file. It will be explained below.
Web. config
<?xml version= "1.0" encoding= "Utf-8"?><configuration> ... <connectionStrings> <add name= "Webresourcecontext" connectionstring= "Data source= (localdb) \v11.0; Initial catalog=webresourcecontext-20141204104407; Integrated security=true; Multipleactiveresultsets=true; attachdbfilename=| datadirectory| Webresourcecontext-20141204104407.mdf " providername=" System.Data.SqlClient "/> </ Connectionstrings> ...</configuration>
In this file, there are a lot of configurations, but the simple one is the one above, and in this statement the local database is now specified; You can also specify a remote data connection.
ControllersResourceApiController.cs
Using system;using system.collections.generic;using system.globalization;using system.io;using System.Linq;using System.net.http;using system.threading.tasks;using system.web;using system.web.http;using System.web.http.description;using webresource.models;namespace webresource.controllers{[RoutePrefix ("Res")] public class Resourceapicontroller:apicontroller {private Webresourcecontext db = new Webresourcecontext (); private static readonly Long memory_size = 64 * 1024 * 1024; private static readonly String Root_path = HttpContext.Current.Server.MapPath ("~/app_data/"); <summary>//Post File///</summary>/<param name= "Id" >Md5</param> <returns>Resource</returns> [HttpPost] [Route ("Upload/{id?}")] [Responsetype (typeof (Resource))] public async task<ihttpactionresult> Post (string Id = null) { list<resource> Resources= new List<resource> (); Multipart/form-data var Provider = new Multipartmemorystreamprovider (); Await Request.Content.ReadAsMultipartAsync (provider); foreach (var item in provider. Contents) {if (item. Headers.ContentDisposition.FileName! = null) {//strem var ms = Item. Readasstreamasync (). Result; using (var br = new BinaryReader (ms)) {if (Ms. Length <= 0) break; var data = br. Readbytes ((int) Ms. Length); Md5 string id = hashutils.getmd5hash (data); Resource temp = await db. Resources.findasync (ID); if (temp = = null) {//create Resource RESOURC E = new Resource (); Resource. id = ID; Resource. Size = Ms. Length; Resource. Cursor = resource. Size; Resource. Published = DateTime.Now; Info FileInfo info = new FileInfo (item. Headers.ContentDisposition.FileName.Replace ("\" "," ")); Resource. Type = info. Extension.substring (1). ToLower (); Resource. Name = info. Name.substring (0, info. Name.lastindexof (".")); Relative Resource. Folder = DateTime.Now.ToString ("yyyymm/dd/", datetimeformatinfo.invariantinfo); Write try {string dirpath = Path.c Ombine (Root_path, resource. Folder); if (! Directory.Exists (Dirpath)) { Directory.CreateDirectory (Dirpath); } file.writeallbytes (Path.Combine (Dirpath, resource. ID), data); Save to Datebase Db. Resources.add (Resource); Await DB. Savechangesasync (); temp = await db. Resources.findasync (Resource. ID); } catch {}} if (temp! = null) Resources. ADD (temp); }}} if (resources. Count = = 0) return badrequest (); else if (resources. Count = = 1) return Ok (resources. FirstOrDefault ()); else return Ok (resources); } }}
This class is the core part of this lecture.
In this class, first look at the first modification, I redirect the API address to:[Routeprefix ("Res")], this is to facilitate later use, input Res is always more than Resource It's better to be comfortable.
In addition I deleted the Get () method, because this version of the main explanation of the upload, the other download will also set the data to operate, so in the next version will be added a new Get ().
Take a look at the current API interface:
Now there's only one interface.
Talk about the process:
- When the upload interface is triggered, the server will store all the uploaded files in memory, and then iterate through each of the uploaded files.
- Computes the MD5 of each file, uses MD5 to query the database for the record, and returns the information in the database directly, if any, without saving the file.
- If not, extract the basic information of the file and add it to the class resource model, then save the file and save the file's information to the database.
- The loop finishes returning the saved results.
Viewupload.cshtml
@{viewbag.title = "Upload";} This file only changes one place, that isaction= "/res/upload"。RunTimeFinally arrived here, to tell the truth to write a very tired.
Run:localhost:60586/home/upload
After submission:
Database
File
You can see that the files are stored according to: Month/day/file MD5.
ENDAs usual.
Resource file[WebApi] Tinkering with a resource Manager-multi-File upload + database assist
Next ChapterIt will be explained in the next chapter, and how to access the file based on this chapter.
========================================================
Qiujuer
Blog: Blog.csdn.net/qiujuer
website: www.qiujuer.net
Open Source Library: genius-android
Reprint Please specify Source: http://blog.csdn.net/qiujuer/article/details/41721165
========================================================
[WebApi] Tinkering with a resource Manager-multi-File upload + database assist