我想通过进行ajax调用使用WebApi上传文件,文件将保存到数据库中。我试过了给出的代码 this link。在这里,它将收到的数据保存为硬盘驱动器,作为没有指定扩展名的文件,但我想做一些事情,比如我将文件保存到数据库时我也希望保存文件名和扩展名,如果我需要的话下载文件我可以提供文件名和扩展名。在链接中,文件作为文件保存到硬盘驱动器,但有任何方法可以直接将文件保存到DB。
答案 0 :(得分:14)
答案有几个部分。
首先,要上传文件,您可以使用包含以下代码的视图:
@using (Html.BeginForm())
{
<input type="file" value="Choose a file"/>
<br/>
<input type="button" value="Upload" id="upload"/>
}
@section scripts
{
<script type="text/javascript">
$(document).ready(function() {
$('#upload').click(function () {
var data = new FormData();
var file = $('form input[type=file]')[0].files[0];
data.append('file',file);
$.ajax({
url: '/Api/File/Upload',
processData: false,
contentType: false,
data: data,
type: 'POST'
}).done(function(result) {
alert(result);
}).fail(function(a, b, c) {
console.log(a, b, c);
});
});
});
</script>
}
其次,要接收此数据,请使用以下方法创建控制器:
public class FileController : ApiController
{
[HttpPost]
public async Task<string> Upload()
{
var provider = new MultipartMemoryStreamProvider();
await Request.Content.ReadAsMultipartAsync(provider);
// extract file name and file contents
var fileNameParam = provider.Contents[0].Headers.ContentDisposition.Parameters
.FirstOrDefault(p => p.Name.ToLower() == "filename");
string fileName = (fileNameParam == null) ? "" : fileNameParam.Value.Trim('"');
byte[] file = await provider.Contents[0].ReadAsByteArrayAsync();
// Here you can use EF with an entity with a byte[] property, or
// an stored procedure with a varbinary parameter to insert the
// data into the DB
var result
= string.Format("Received '{0}' with length: {1}", fileName, file.Length);
return result;
}
}
第三,默认情况下,最大上传大小是有限的。您可以克服此限制修改web.config
:
在maxRequestLength="max size in bytes"
中添加<configuration><system.web><httpRuntime>
。 (或者如果它不存在则创建这个元素):
将maxAllowedContentLength
添加到<configuration><system.web><security><requestFiltering><requestLimits>
元素(如果它不存在,则创建此元素)
这些条目如下所示:
<configuration>
<system.web>
<!-- kilobytes -->
<httpRuntime targetFramework="4.5" maxRequestLength="2000000" />
<configuration>
<system.webServer>
<security>
<requestFiltering>
<!-- bytes -->
<requestLimits maxAllowedContentLength="2000000000"/>
注意:您应该将其包含在<location>
元素中,以便此限制仅应用于上载文件的特定路径,如下所示:
<location path="Api/File/Upload">
<system.web>
...
<system.webServer>
...
请注意修改根web.config
,而不是Views
文件夹中的根。{/ p>
第四,关于在数据库中保存数据,如果你使用EF,你只需要一个这样的实体:
public class File
{
public int FileId { get; set; }
public string FileName { get; set; }
public byte[] FileContent { get; set; }
}
创建此类的新对象,添加到上下文并保存更改。
如果您使用存储过程,请创建一个具有varbinary
参数的存储过程,并将byte[] file
作为值传递。
答案 1 :(得分:3)
使用webAPI控制器执行此操作的更简洁方法如下:
创建一个web api控制器文件: 的 UploadFileController.cs 强>
public class UploadFileController : ApiController
{
// POST api/<controller>
public HttpResponseMessage Post()
{
HttpResponseMessage result = null;
var httpRequest = HttpContext.Current.Request;
if (httpRequest.Files.Count > 0)
{
var docfiles = new List<string>();
foreach (string file in httpRequest.Files)
{
var postedFile = httpRequest.Files[file];
int hasheddate = DateTime.Now.GetHashCode();
//Good to use an updated name always, since many can use the same file name to upload.
string changed_name = hasheddate.ToString() + "_" + postedFile.FileName;
var filePath = HttpContext.Current.Server.MapPath("~/Images/" + changed_name);
postedFile.SaveAs(filePath); // save the file to a folder "Images" in the root of your app
changed_name = @"~\Images\" + changed_name; //store this complete path to database
docfiles.Add(changed_name);
}
result = Request.CreateResponse(HttpStatusCode.Created, docfiles);
}
else
{
result = Request.CreateResponse(HttpStatusCode.BadRequest);
}
return result;
}
}
在标记中使用此webAPI。使用以下:
<input type="hidden" id="insertPicture" />
<input id="insertFileupload" type="file" name="files[]" accept="image/*" data-url="/api/uploadfile" multiple>
<script>
$(function () {
$('#insertFileupload').fileupload({
add: function (e, data) {
var jqXHR = data.submit()
.success(function (result, textStatus, jqXHR) {/* ... */
$('#insertPicture').val(result);
alert("File Uploaded");
})
.error(function (jqXHR, textStatus, errorThrown) {/* ... */
alert(errorThrown);
})
}
});
});
您可以在输入标记的“accept”属性中更改文件类型(要接受的扩展名)。 希望它会有所帮助!享受!
答案 2 :(得分:1)
如果要将文件保存到数据库中的BLOB
字段,则可以使用以下帖子中提供的代码:Saving any file to in the database, just convert it to a byte array?。
相关代码如下:
public static int databaseFilePut(MemoryStream fileToPut)
{
int varID = 0;
byte[] file = fileToPut.ToArray();
const string preparedCommand = @"
INSERT INTO [dbo].[Raporty]
([RaportPlik])
VALUES
(@File)
SELECT [RaportID] FROM [dbo].[Raporty]
WHERE [RaportID] = SCOPE_IDENTITY()
";
using (var varConnection = Locale.sqlConnectOneTime(Locale.sqlDataConnectionDetails))
using (var sqlWrite = new SqlCommand(preparedCommand, varConnection))
{
sqlWrite.Parameters.Add("@File", SqlDbType.VarBinary, file.Length).Value = file;
using (var sqlWriteQuery = sqlWrite.ExecuteReader())
while (sqlWriteQuery != null && sqlWriteQuery.Read())
varID = sqlWriteQuery["RaportID"] is int ? (int) sqlWriteQuery["RaportID"] : 0;
}
return varID;
}
您可以将发送链接中的方法与用于提交MemoryStream
的代码的方法结合到我链接到的答案中提供的数据库中。
您需要在表中使用特定列来保存实际文件名。基本上,您需要文件内容的BLOB
列和文件名的另一个TEXT
或VARCHAR
列。您提供的链接显示了获取文件名称的方法。
但是,正如其他人指出的那样,您不应该将文件保存到数据库中。处理文件上载的最常用方法是将它们保存到服务器上的某个位置,并将保存文件的路径提交到数据库中的TEXT
或VARCHAR
字段。
答案 3 :(得分:0)
您无法直接将文件保存到数据库中。
除了在本地保存文件之外,其中一个选项是将其保存到内存流中,然后将其传递给数据库。这个问题可以为您提供代码示例,说明如何获取文件名和扩展名并将文件保存到内存中:Web API: how to access multipart form values when using MultipartMemoryStreamProvider?
答案 4 :(得分:0)
我认为你想要实现的目标在这个previous question
中得到了部分回答现在,关于直接保存到数据库,您应该能够实现这一点,而不必先将文件保存到硬盘驱动器,通常是通过获取流字节数组并将其作为byte []放入数据库实体或行属性中(字节数组)
答案 5 :(得分:0)
js代码如下。
var Sendmodel = new FormData();Sendmodel.append("TemplatePath",$('#fileTemplatePath')[0].files[0]);Sendmodel.append("Name","pradip");
$.ajax({
url: "api/project/SaveCertificateSettings",
type: 'POST',
contentType: false,
processData: false,
data: Sendmodel,
success: function (data, textStatus, xhr) {
},
error: function (xhr, textStatus, errorThrown) {
alert('error');
}
});
如下所示的Web api代码。
public object SaveCertificateSettings()
{
string Name = Convert.ToString(HttpContext.Current.Request.Form["Name"]);
if (HttpContext.Current.Request.Files.AllKeys.Any())
{
// Get the uploaded image from the Files collection
var httpPostedFile = HttpContext.Current.Request.Files["TemplatePath"];
if (httpPostedFile != null)
{
// httpPostedFile.FileName;
// Get the complete file path
}
}
}