(前言:這個問題是關於2011年發佈的 ASP.NET MVC 3.0,它不是關於2019年發佈的ASP.NET Core 3.0 ) html
我想在asp.net-mvc上傳文件。 如何使用html input file
控件上傳input file
? web
在視圖中: ajax
<form action="Categories/Upload" enctype="multipart/form-data" method="post"> <input type="file" name="Image"> <input type="submit" value="Save"> </form>
而控制器中的如下代碼: 數據庫
public ActionResult Upload() { foreach (string file in Request.Files) { var hpf = this.Request.Files[file]; if (hpf.ContentLength == 0) { continue; } string savedFileName = Path.Combine( AppDomain.CurrentDomain.BaseDirectory, "PutYourUploadDirectoryHere"); savedFileName = Path.Combine(savedFileName, Path.GetFileName(hpf.FileName)); hpf.SaveAs(savedFileName); } ... }
傳輸到byte []的替代方法(用於保存到DB)。 mvc
@Arthur的方法效果很好,但不能很好地複製,所以MS Office文檔在從數據庫中檢索後可能沒法打開。 MemoryStream.GetBuffer()能夠在byte []的末尾返回額外的空字節,但您能夠經過使用MemoryStream.ToArray()來修復它。 可是,我發現這種替代方法適用於全部文件類型: app
using (var binaryReader = new BinaryReader(file.InputStream)) { byte[] array = binaryReader.ReadBytes(file.ContentLength); }
這是個人完整代碼: asp.net
文件類: async
public class Document { public int? DocumentID { get; set; } public string FileName { get; set; } public byte[] Data { get; set; } public string ContentType { get; set; } public int? ContentLength { get; set; } public Document() { DocumentID = 0; FileName = "New File"; Data = new byte[] { }; ContentType = ""; ContentLength = 0; } }
文件下載: ide
[HttpGet] public ActionResult GetDocument(int? documentID) { // Get document from database var doc = dataLayer.GetDocument(documentID); // Convert to ContentDisposition var cd = new System.Net.Mime.ContentDisposition { FileName = doc.FileName, // Prompt the user for downloading; set to true if you want // the browser to try to show the file 'inline' (display in-browser // without prompting to download file). Set to false if you // want to always prompt them to download the file. Inline = true, }; Response.AppendHeader("Content-Disposition", cd.ToString()); // View document return File(doc.Data, doc.ContentType); }
上傳文件: post
[HttpPost] public ActionResult GetDocument(HttpPostedFileBase file) { // Verify that the user selected a file if (file != null && file.ContentLength > 0) { // Get file info var fileName = Path.GetFileName(file.FileName); var contentLength = file.ContentLength; var contentType = file.ContentType; // Get file data byte[] data = new byte[] { }; using (var binaryReader = new BinaryReader(file.InputStream)) { data = binaryReader.ReadBytes(file.ContentLength); } // Save to database Document doc = new Document() { FileName = fileName, Data = data, ContentType = contentType, ContentLength = contentLength, }; dataLayer.SaveDocument(doc); // Show success ... return RedirectToAction("Index"); } else { // Show error ... return View("Foo"); } }
查看(摘錄):
@using (Html.BeginForm("GetDocument", "Home", FormMethod.Post, new { enctype = "multipart/form-data" })) { <input type="file" name="file" /> <input type="submit" value="Upload File" /> }
一般你也但願傳遞一個viewmodel,而不是惟一一個文件。 在下面的代碼中,您將找到一些其餘有用的功能:
能夠經過如下代碼完成:
[HttpPost] public ActionResult Index(MyViewModel viewModel) { // if file's content length is zero or no files submitted if (Request.Files.Count != 1 || Request.Files[0].ContentLength == 0) { ModelState.AddModelError("uploadError", "File's length is zero, or no files found"); return View(viewModel); } // check the file size (max 4 Mb) if (Request.Files[0].ContentLength > 1024 * 1024 * 4) { ModelState.AddModelError("uploadError", "File size can't exceed 4 MB"); return View(viewModel); } // check the file size (min 100 bytes) if (Request.Files[0].ContentLength < 100) { ModelState.AddModelError("uploadError", "File size is too small"); return View(viewModel); } // check file extension string extension = Path.GetExtension(Request.Files[0].FileName).ToLower(); if (extension != ".pdf" && extension != ".doc" && extension != ".docx" && extension != ".rtf" && extension != ".txt") { ModelState.AddModelError("uploadError", "Supported file extensions: pdf, doc, docx, rtf, txt"); return View(viewModel); } // extract only the filename var fileName = Path.GetFileName(Request.Files[0].FileName); // store the file inside ~/App_Data/uploads folder var path = Path.Combine(Server.MapPath("~/App_Data/uploads"), fileName); try { if (System.IO.File.Exists(path)) System.IO.File.Delete(path); Request.Files[0].SaveAs(path); } catch (Exception) { ModelState.AddModelError("uploadError", "Can't save file to disk"); } if(ModelState.IsValid) { // put your logic here return View("Success"); } return View(viewModel); }
確保你有
@Html.ValidationMessage("uploadError")
在您的視圖中驗證錯誤。
另請注意,默認最大請求長度爲4MB(maxRequestLength = 4096),要上傳較大的文件,您必須在web.config中更改此參數:
<system.web> <httpRuntime maxRequestLength="40960" executionTimeout="1100" />
(40960 = 40 MB)。
執行超時是整秒數。 您可能想要更改它以容許上傳大文件。
public ActionResult FileUpload(upload mRegister) { //Check server side validation using data annotation if (ModelState.IsValid) { //TO:DO var fileName = Path.GetFileName(mRegister.file.FileName); var path = Path.Combine(Server.MapPath("~/Content/Upload"), fileName); mRegister.file.SaveAs(path); ViewBag.Message = "File has been uploaded successfully"; ModelState.Clear(); } return View(); }
我必須使用命令上傳100 kb文件塊中的文件和上傳文件存儲在數據庫中。 我但願,它對你有所幫助。
public HttpResponseMessage Post(AttachmentUploadForm form) { var response = new WebApiResultResponse { IsSuccess = true, RedirectRequired = false }; var tempFilesFolder = Sanelib.Common.SystemSettings.Globals.CreateOrGetCustomPath("Temp\\" + form.FileId); File.WriteAllText(tempFilesFolder + "\\" + form.ChunkNumber + ".temp", form.ChunkData); if (form.ChunkNumber < Math.Ceiling((double)form.Size / 102400)) return Content(response); var folderInfo = new DirectoryInfo(tempFilesFolder); var totalFiles = folderInfo.GetFiles().Length; var sb = new StringBuilder(); for (var i = 1; i <= totalFiles; i++) { sb.Append(File.ReadAllText(tempFilesFolder + "\\" + i + ".temp")); } var base64 = sb.ToString(); base64 = base64.Substring(base64.IndexOf(',') + 1); var fileBytes = Convert.FromBase64String(base64); var fileStream = new FileStream(tempFilesFolder + "\\" + form.Name, FileMode.OpenOrCreate, FileAccess.ReadWrite); fileStream.Seek(fileStream.Length, SeekOrigin.Begin); fileStream.Write(fileBytes, 0, fileBytes.Length); fileStream.Close(); Directory.Delete(tempFilesFolder, true); var md5 = MD5.Create(); var command = Mapper.Map<AttachmentUploadForm, AddAttachment>(form); command.FileData = fileBytes; command.FileHashCode = BitConverter.ToString(md5.ComputeHash(fileBytes)).Replace("-", ""); return ExecuteCommand(command); }
Javascript(淘汰賽Js)
define(['util', 'ajax'], function (util, ajax) { "use strict"; var exports = {}, ViewModel, Attachment, FileObject; //File Upload FileObject = function (file, parent) { var self = this; self.fileId = util.guid(); self.name = ko.observable(file.name); self.type = ko.observable(file.type); self.size = ko.observable(); self.fileData = null; self.fileSize = ko.observable(file.size / 1024 / 1024); self.chunks = 0; self.currentChunk = ko.observable(); var reader = new FileReader(); // Closure to capture the file information. reader.onload = (function (e) { self.fileData = e.target.result; self.size(self.fileData.length); self.chunks = Math.ceil(self.size() / 102400); self.sendChunk(1); }); reader.readAsDataURL(file); self.percentComplete = ko.computed(function () { return self.currentChunk() * 100 / self.chunks; }, self); self.cancel = function (record) { parent.uploads.remove(record); }; self.sendChunk = function (number) { var start = (number - 1) * 102400; var end = number * 102400; self.currentChunk(number); var form = { fileId: self.fileId, name: self.name(), fileType: self.type(), Size: self.size(), FileSize: self.fileSize(), chunkNumber: number, chunkData: self.fileData.slice(start, end), entityTypeValue: parent.entityTypeValue, ReferenceId: parent.detail.id, ReferenceName: parent.detail.name }; ajax.post('Attachment', JSON.stringify(form)).done(function (response) { if (number < self.chunks) self.sendChunk(number + 1); if (response.id != null) { parent.attachments.push(new Attachment(response)); self.cancel(response); } }); }; }; Attachment = function (data) { var self = this; self.id = ko.observable(data.id); self.name = ko.observable(data.name); self.fileType = ko.observable(data.fileType); self.fileSize = ko.observable(data.fileSize); self.fileData = ko.observable(data.fileData); self.typeName = ko.observable(data.typeName); self.description = ko.observable(data.description).revertable(); self.tags = ko.observable(data.tags).revertable(); self.operationTime = ko.observable(moment(data.createdOn).format('MM-DD-YYYY HH:mm:ss')); self.description.subscribe(function () { var form = { Id: self.id(), Description: self.description(), Tags: self.tags() }; ajax.put('attachment', JSON.stringify(form)).done(function (response) { self.description.commit(); return; }).fail(function () { self.description.revert(); }); }); self.tags.subscribe(function () { var form = { Id: self.id(), Description: self.description(), Tags: self.tags() }; ajax.put('attachment', JSON.stringify(form)).done(function (response) { self.tags.commit(); return; }).fail(function () { self.tags.revert(); }); }); }; ViewModel = function (data) { var self = this; // for attachment self.attachments = ko.observableArray([]); $.each(data.attachments, function (row, val) { self.attachments.push(new Attachment(val)); }); self.deleteAttachmentRecord = function (record) { if (!confirm("Are you sure you want to delete this record?")) return; ajax.del('attachment', record.id(), { async: false }).done(function () { self.attachments.remove(record); return; }); }; exports.exec = function (model) { console.log(model); var viewModel = new ViewModel(model); ko.applyBindings(viewModel, document.getElementById('ShowAuditDiv')); }; return exports; });
HTML代碼:
<div class="row-fluid spacer-bottom fileDragHolder"> <div class="spacer-bottom"></div> <div class="legend"> Attachments<div class="pull-right">@Html.AttachmentPicker("AC")</div> </div> <div> <div class="row-fluid spacer-bottom"> <div style="overflow: auto"> <table class="table table-bordered table-hover table-condensed" data-bind="visible: uploads().length > 0 || attachments().length > 0"> <thead> <tr> <th class=" btn btn-primary col-md-2" style="text-align: center"> Name </th> <th class="btn btn-primary col-md-1" style="text-align: center">Type</th> <th class="btn btn-primary col-md-1" style="text-align: center">Size (MB)</th> <th class="btn btn-primary col-md-1" style="text-align: center">Upload Time</th> <th class="btn btn-primary col-md-1" style="text-align: center">Tags</th> <th class="btn btn-primary col-md-6" style="text-align: center">Description</th> <th class="btn btn-primary col-md-1" style="text-align: center">Delete</th> </tr> </thead> <tbody> <!-- ko foreach: attachments --> <tr> <td style="text-align: center" class="col-xs-2"><a href="#" data-bind="text: name,attr:{'href':'/attachment/index?id=' + id()}"></a></td> <td style="text-align: center" class="col-xs-1"><span data-bind="text: fileType"></span></td> <td style="text-align: center" class="col-xs-1"><span data-bind="text: fileSize"></span></td> <td style="text-align: center" class="col-xs-2"><span data-bind="text: operationTime"></span></td> <td style="text-align: center" class="col-xs-3"><div contenteditable="true" data-bind="editableText: tags"></div></td> <td style="text-align: center" class="col-xs-4"><div contenteditable="true" data-bind="editableText: description"></div></td> <td style="text-align: center" class="col-xs-1"><button class="btn btn-primary" data-bind="click:$root.deleteAttachmentRecord"><i class="icon-trash"></i></button></td> </tr> <!-- /ko --> </tbody> <tfoot data-bind="visible: uploads().length > 0"> <tr> <th colspan="6">Files upload status</th> </tr> <tr> <th>Name</th> <th>Type</th> <th>Size (MB)</th> <th colspan="2">Status</th> <th></th> </tr> <!-- ko foreach: uploads --> <tr> <td><span data-bind="text: name"></span></td> <td><span data-bind="text: type"></span></td> <td><span data-bind="text: fileSize"></span></td> <td colspan="2"> <div class="progress"> <div class="progress-bar" data-bind="style: { width: percentComplete() + '%' }"></div> </div> </td> <td style="text-align: center"><button class="btn btn-primary" data-bind="click:cancel"><i class="icon-trash"></i></button></td> </tr> <!-- /ko --> </tfoot> </table> </div> <div data-bind="visible: attachments().length == 0" class="span12" style="margin-left:0"> <span>No Records found.</span> </div> </div>