(前言:这个问题是关于2011年发布的ASP.NET MVC 3.0,而不是关于2019年发布的ASP.NETCore 3.0)
我想用asp.net mvc上传文件。如何使用html输入文件控件上载文件?
(前言:这个问题是关于2011年发布的ASP.NET MVC 3.0,而不是关于2019年发布的ASP.NETCore 3.0)
我想用asp.net mvc上传文件。如何使用html输入文件控件上载文件?
当前回答
尽管我在donnetfiddle上为你做了一个示例项目,但大多数答案似乎都足够合理
我正在使用LumenWorks.Framework进行CSV工作,但这不是必须的。
Demo
View
@using (Html.BeginForm("Index", "Home", "POST"))
{
<div class="form-group">
<label for="file">Upload Files:</label>
<input type="file" multiple name="files" id="files" class="form-control"/><br><br>
<input type="submit" value="Upload Files" class="form-control"/>
</div>
控制器:
[HttpPost]
public ActionResult Index(HttpPostedFileBase upload)
{
if (ModelState.IsValid)
{
if (upload != null && upload.ContentLength > 0)
{
// Validation content length
if (upload.FileName.EndsWith(".csv") || upload.FileName.EndsWith(".CSV"))
{
//extention validation
ViewBag.Result = "Correct File Uploaded";
}
}
}
return View();
}
其他回答
要传输到字节[](例如,用于保存到DB):
using (MemoryStream ms = new MemoryStream()) {
file.InputStream.CopyTo(ms);
byte[] array = ms.GetBuffer();
}
若要将输入流直接传输到数据库中,而不将其存储在内存中,您可以使用从此处获取的此类,并稍作更改:
public class VarbinaryStream : Stream {
private SqlConnection _Connection;
private string _TableName;
private string _BinaryColumn;
private string _KeyColumn;
private int _KeyValue;
private long _Offset;
private SqlDataReader _SQLReader;
private long _SQLReadPosition;
private bool _AllowedToRead = false;
public VarbinaryStream(
string ConnectionString,
string TableName,
string BinaryColumn,
string KeyColumn,
int KeyValue,
bool AllowRead = false)
{
// create own connection with the connection string.
_Connection = new SqlConnection(ConnectionString);
_TableName = TableName;
_BinaryColumn = BinaryColumn;
_KeyColumn = KeyColumn;
_KeyValue = KeyValue;
// only query the database for a result if we are going to be reading, otherwise skip.
_AllowedToRead = AllowRead;
if (_AllowedToRead == true)
{
try
{
if (_Connection.State != ConnectionState.Open)
_Connection.Open();
SqlCommand cmd = new SqlCommand(
@"SELECT TOP 1 [" + _BinaryColumn + @"]
FROM [dbo].[" + _TableName + @"]
WHERE [" + _KeyColumn + "] = @id",
_Connection);
cmd.Parameters.Add(new SqlParameter("@id", _KeyValue));
_SQLReader = cmd.ExecuteReader(
CommandBehavior.SequentialAccess |
CommandBehavior.SingleResult |
CommandBehavior.SingleRow |
CommandBehavior.CloseConnection);
_SQLReader.Read();
}
catch (Exception e)
{
// log errors here
}
}
}
// this method will be called as part of the Stream ímplementation when we try to write to our VarbinaryStream class.
public override void Write(byte[] buffer, int index, int count)
{
try
{
if (_Connection.State != ConnectionState.Open)
_Connection.Open();
if (_Offset == 0)
{
// for the first write we just send the bytes to the Column
SqlCommand cmd = new SqlCommand(
@"UPDATE [dbo].[" + _TableName + @"]
SET [" + _BinaryColumn + @"] = @firstchunk
WHERE [" + _KeyColumn + "] = @id",
_Connection);
cmd.Parameters.Add(new SqlParameter("@firstchunk", buffer));
cmd.Parameters.Add(new SqlParameter("@id", _KeyValue));
cmd.ExecuteNonQuery();
_Offset = count;
}
else
{
// for all updates after the first one we use the TSQL command .WRITE() to append the data in the database
SqlCommand cmd = new SqlCommand(
@"UPDATE [dbo].[" + _TableName + @"]
SET [" + _BinaryColumn + @"].WRITE(@chunk, NULL, @length)
WHERE [" + _KeyColumn + "] = @id",
_Connection);
cmd.Parameters.Add(new SqlParameter("@chunk", buffer));
cmd.Parameters.Add(new SqlParameter("@length", count));
cmd.Parameters.Add(new SqlParameter("@id", _KeyValue));
cmd.ExecuteNonQuery();
_Offset += count;
}
}
catch (Exception e)
{
// log errors here
}
}
// this method will be called as part of the Stream ímplementation when we try to read from our VarbinaryStream class.
public override int Read(byte[] buffer, int offset, int count)
{
try
{
long bytesRead = _SQLReader.GetBytes(0, _SQLReadPosition, buffer, offset, count);
_SQLReadPosition += bytesRead;
return (int)bytesRead;
}
catch (Exception e)
{
// log errors here
}
return -1;
}
public override bool CanRead
{
get { return _AllowedToRead; }
}
protected override void Dispose(bool disposing)
{
if (_Connection != null)
{
if (_Connection.State != ConnectionState.Closed)
try { _Connection.Close(); }
catch { }
_Connection.Dispose();
}
base.Dispose(disposing);
}
#region unimplemented methods
public override bool CanSeek
{
get { return false; }
}
public override bool CanWrite
{
get { return true; }
}
public override void Flush()
{
throw new NotImplementedException();
}
public override long Length
{
get { throw new NotImplementedException(); }
}
public override long Position
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotImplementedException();
}
public override void SetLength(long value)
{
throw new NotImplementedException();
}
#endregion unimplemented methods }
以及用法:
using (var filestream = new VarbinaryStream(
"Connection_String",
"Table_Name",
"Varbinary_Column_name",
"Key_Column_Name",
keyValueId,
true))
{
postedFile.InputStream.CopyTo(filestream);
}
我必须上传100kb的文件块,最后一个上传文件使用命令存储在数据库中。我希望,这会对你有所帮助。
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(Knockout 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>
保存多个文件的简单方法
cshtml
@using (Html.BeginForm("Index","Home",FormMethod.Post,new { enctype = "multipart/form-data" }))
{
<label for="file">Upload Files:</label>
<input type="file" multiple name="files" id="files" /><br><br>
<input type="submit" value="Upload Files" />
<br><br>
@ViewBag.Message
}
控制器
[HttpPost]
public ActionResult Index(HttpPostedFileBase[] files)
{
foreach (HttpPostedFileBase file in files)
{
if (file != null && file.ContentLength > 0)
try
{
string path = Path.Combine(Server.MapPath("~/Files"), Path.GetFileName(file.FileName));
file.SaveAs(path);
ViewBag.Message = "File uploaded successfully";
}
catch (Exception ex)
{
ViewBag.Message = "ERROR:" + ex.Message.ToString();
}
else
{
ViewBag.Message = "You have not specified a file.";
}
}
return View();
}
如果你碰巧像我一样在这里跌跌撞撞,想知道尽管代码正确,为什么你的代码仍然不工作。然后,请在输入控件中查找name属性,您可能会意外错过或从未将其放在首位。
<input class="custom-file-input" name="UploadFile" id="UploadFile" type="file" onchange="ValidateFile(this);" accept=".xls, .xlsx">
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();
}