I need to allow image upload in my AngularJS + WebAPI project. to achieve this I am using ng-file-upload according to this sample code: http://monox.mono-software.com/blog/post/Mono/233/Async-upload-using-angular-file-upload-directive-and-net-WebAPI-service/
with a few adjustments to the post code to look like this:
$scope.onFileSelect = function ($files) {
console.log("on file select is running!");
//$files: an array of files selected, each file has name, size, and type.
for (var i = 0; i < $files.length; i++) {
var $file = $files[i];
(function (index) {
Upload.upload({
url: "/api/Uploads/Upload", // webapi url
method: "POST",
file: $file
}).progress(function (evt) {
// get upload percentage
console.log('percent: ' + parseInt(100.0 * evt.loaded / evt.total));
}).success(function (data, status, headers, config) {
// file is uploaded successfully
console.log(data);
}).error(function (data, status, headers, config) {
// file failed to upload
console.log(data);
});
})(i);
}
}
I have quite a few web API controllers already and I added a new one according to the code sample in the link above (that inherits from System.web.http.ApiController instead of the "regular" Microsoft.AspNet.Mvc.Controller class):
[Route("api/[controller]")]
public class UploadsController : ApiController
{
[HttpPost] // This is from System.Web.Http, and not from System.Web.Mvc
public async Task<HttpResponseMessage> Upload()
{
if (!Request.Content.IsMimeMultipartContent())
{
this.Request.CreateResponse(HttpStatusCode.UnsupportedMediaType);
}
var provider = GetMultipartProvider();
var result = await Request.Content.ReadAsMultipartAsync(provider);
// On upload, files are given a generic name like "BodyPart_26d6abe1-3ae1-416a-9429-b35f15e6e5d5"
// so this is how you can get the original file name
var originalFileName = GetDeserializedFileName(result.FileData.First());
// uploadedFileInfo object will give you some additional stuff like file length,
// creation time, directory name, a few filesystem methods etc..
var uploadedFileInfo = new FileInfo(result.FileData.First().LocalFileName);
// Through the request response you can return an object to the Angular controller
// You will be able to access this in the .success callback through its data attribute
// If you want to send something to the .error callback, use the HttpStatusCode.BadRequest instead
var returnData = "ReturnTest";
return this.Request.CreateResponse(HttpStatusCode.OK, new { returnData });
}
The problem is, i keep getting "404 not found" when posting.
I tried:
all stack overflow answers
online answers
removing the content of the "Upload" function, and changing to MVC's Controller base class -> still same result.
changing the name of "Upload" method to "Post" and posting to "/api/uploads" -> same 404.
Please help! thanks!
EDIT
this is the browser "Network" tab:
I am using HTTPS
this was tested "live" (without localhost) = same result.
EDIT2
my routes:
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
these are the only routes that are declared.
EDIT3
I am 100% sure the problem is me using " ApiController " as base class instead of " Controller ". i added a new controller and i can access it no problem. now just making it work as i don't have " Request.Content " in " Controller " - any ideas?
I see 2 possibilities to make it work:
pass HttpRequestMessage as a parameter to the method:
public async Task Post([FromBody]HttpRequestMessage request)
but i am getting HTTP 500 as i don't know how to pass from angular's POST.
or:
has someone managed to do this? thanks!
I was able to solve the problem i posted in EDIT3 by using:
if (Request.Form.Files != null && Request.Form.Files.Count > 0)
{
var file = Request.Form.Files[0];
var contentType = file.ContentType;
using (var fileStream = file.OpenReadStream())
{
using (var memoryStream = new MemoryStream())
{
await fileStream.CopyToAsync(memoryStream);
FileStream newFS = new FileStream(Settings.UserImagesDir + "\\name.png", FileMode.Create);
memoryStream.WriteTo(newFS);
newFS.Close();
}
}
}
and all this in a regular web api controller that inherits from Controller .
thanks everyone for your help, although no one solved it you all pushed me in the right direction.
The problem is that your routing is misconfigured for the URL /api/Uploads/Upload
. In order to make it match, you have to specify a template for the method Upload
, since it is not actually named after an HTTP method.
[HttpPost("upload")]
public async Task<HttpResponseMessage> Upload()
{
// code omitted...
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.