I want to upload file using a WebApi by making an ajax call and the file will save into database. I tried the code given in the this link. Here, it is saved the received data to hard drive as a file with no extension specified but I want to do something like when I'm saving the file to Database I also want to save the file name and the extension cause later if I need to download the file I can provide the file name and extension with it. And in the link the file is saved to hard drive as a file but is there any way that I can directly save the file to DB.
-
2it's realy hard to read this message... Could you please rewrite it? Try using short sentenses. – IAfanasov Jan 12 '15 at 12:28
-
http://www.codeproject.com/Articles/806075/File-Upload-using-jQuery-AJAX-in-ASP-NET-Web-API – Greg Jan 12 '15 at 18:07
6 Answers
The answer has several parts.
First, to upload the file, you can use a view with code like this:
@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>
}
Second, to receive this data, create a controller, with a method like this:
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;
}
}
Third, by default the maximum upload size is limited. You can overcome this limitations modifying web.config
:
Add
maxRequestLength="max size in bytes"
in<configuration><system.web><httpRuntime>
. (Or create this lement if it doesn't exist):Add
maxAllowedContentLength
to<configuration><system.web><security><requestFiltering><requestLimits>
element (or create this element if it doesn't exist)
These entries look like this:
<configuration>
<system.web>
<!-- kilobytes -->
<httpRuntime targetFramework="4.5" maxRequestLength="2000000" />
<configuration>
<system.webServer>
<security>
<requestFiltering>
<!-- bytes -->
<requestLimits maxAllowedContentLength="2000000000"/>
NOTE: you should include this inside a <location>
element, so that this limits are only applied to the particular route where the files are uploaded, like this:
<location path="Api/File/Upload">
<system.web>
...
<system.webServer>
...
Beware to modify the root web.config
, not the one in the Views
folder.
Fourth, as to saving the data in the database, if you use EF, you simply need an entity like this:
public class File
{
public int FileId { get; set; }
public string FileName { get; set; }
public byte[] FileContent { get; set; }
}
Create a new object of this class, add to the context and save changes.
If you use stored procedures, create one which has a varbinary
parameter, and pass the byte[] file
as value.

- 38,030
- 8
- 98
- 117
-
-
-
@HeemanshuBhalla, because it's async and using await. Better explanation: https://blog.stephencleary.com/2012/02/async-and-await.html – Alex Mar 28 '23 at 18:34
A cleaner way to do this using webAPI controller is as follows:
Create a web api controller file: 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;
}
}
To use this webAPI in your markup. Use following:
<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);
})
}
});
});
You can change the type of file (extensions to accept) in the "accept" attribute of the input tag. Hope it will help! Enjoy!

- 1,123
- 10
- 17
-
1Why do you consider this cleaner? You are using HttpContext.Current and looking for a specific server variable via string. And why are you getting a hashed DateTime.Now and taking first 4 of that. Seems expensive way to generate a name. – MPavlak Jan 29 '16 at 04:04
-
@MPavlak Both of the two things were specific to a requirement in my code. I agree, these should/not be used by everyone. I am updating my answer. Thanks for pointing. – vohrahul Apr 20 '16 at 05:56
You can't directly save file to the database.
One of the options, apart from saving the file locally, is saving it into the memory stream and then passing it to the database. This question can give you the code example of how you can get the filename and extension and save the file into the memory: Web API: how to access multipart form values when using MultipartMemoryStreamProvider?

- 1
- 1

- 12,074
- 1
- 49
- 50
I think what you want to achieve here is partly answered in this previous question
Now, about saving directly to database, you should be able to achieve this without saving the file to a hard drive first, normally by taking the stream byte array and putting it into your database entity or row property as a byte[] (array of bytes)
If you want to save the file to a BLOB
field in your database, then you can use the code provided in the following post: Saving any file to in the database, just convert it to a byte array?.
The relevant code is below:
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;
}
You can combine the approach in the link you sent with the code for committing a MemoryStream
to the database provided in an answer I linked to.
You will need a specific column in your table to save the actual file name. Basically, you will need a BLOB
column for the file content and another TEXT
or VARCHAR
column for the file name. The link you provided shows a way to obtain the name of the file.
However, as others have pointed out, you should not save files to the database. The most common way of handling file uploads is to save them to some location on the server and commit the path to the saved file to a TEXT
or VARCHAR
field in the database.
js code as below.
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 code as below.
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
}
}
}

- 109
- 1
- 3