31

How I can upload Image File via ASP.NET Web API?
I have an input tag in File mode and it posted to API, how I can save it to server folder?
I tried this code but it doesn't worked:

private void UploadWholeFile(HttpRequestBase request)
{
   for (int i = 0; i < request.Files.Count; i++)
   {
      var file = request.Files[i];

      var ext = new FileInfo(file.FileName).Extension;
      var fullPath = Path.Combine(StorageRoot, Path.GetFileName(Guid.NewGuid() + ext));

      file.SaveAs(fullPath);
   }
}
Mazdak Shojaie
  • 1,620
  • 1
  • 25
  • 32
AmirReza
  • 311
  • 1
  • 3
  • 6
  • 1
    There can be a number of things that are going wrong. For instance your app might not be authorized to write files in that particular folder. Are you getting an exception? If so what is it? If you don't see the "yellow screen of death" in your browser look for the response to that post using developer tools or surround your method's code with a try catch and watch-debug or log the exception. – Eduard Dumitru Aug 05 '15 at 18:17
  • 1
    There is a great article on Microsoft website with an example [Sending HTML Form Data in ASP.NET Web API: File Upload and Multipart MIME](https://learn.microsoft.com/en-us/aspnet/web-api/overview/advanced/sending-html-form-data-part-2) – Aliaksei Maniuk Mar 21 '18 at 18:47

6 Answers6

36

Here I have described the whole process to upload the image in web api

[Route("user/PostUserImage")]
public async Task<HttpResponseMessage> PostUserImage()
{
    Dictionary<string, object> dict = new Dictionary<string, object>();
    try
    {
        var httpRequest = HttpContext.Current.Request;

        foreach (string file in httpRequest.Files)
        {
            HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created);

            var postedFile = httpRequest.Files[file];
            if (postedFile != null && postedFile.ContentLength > 0)
            {
                int MaxContentLength = 1024 * 1024 * 1; //Size = 1 MB
                IList<string> AllowedFileExtensions = new List<string> { ".jpg", ".gif", ".png" };
                var ext = postedFile.FileName.Substring(postedFile.FileName.LastIndexOf('.'));
                var extension = ext.ToLower();
                if (!AllowedFileExtensions.Contains(extension))
                {
                    var message = string.Format("Please Upload image of type .jpg,.gif,.png.");

                    dict.Add("error", message);
                    return Request.CreateResponse(HttpStatusCode.BadRequest, dict);
                }
                else if (postedFile.ContentLength > MaxContentLength)
                {
                    var message = string.Format("Please Upload a file upto 1 mb.");

                    dict.Add("error", message);
                    return Request.CreateResponse(HttpStatusCode.BadRequest, dict);
                }
                else
                {
                    YourModelProperty.imageurl = userInfo.email_id + extension;
                    //  where you want to attach your imageurl

                    //if needed write the code to update the table

                    var filePath = HttpContext.Current.Server.MapPath("~/Userimage/" + userInfo.email_id + extension);
                    //Userimage myfolder name where I want to save my image
                    postedFile.SaveAs(filePath);
                }
            }

            var message1 = string.Format("Image Updated Successfully.");
            return Request.CreateErrorResponse(HttpStatusCode.Created, message1); ;
        }

        var res = string.Format("Please Upload a image.");
        dict.Add("error", res);
        return Request.CreateResponse(HttpStatusCode.NotFound, dict);
    }
    catch (Exception ex)
    {
        var res = string.Format("some Message");
        dict.Add("error", res);
        return Request.CreateResponse(HttpStatusCode.NotFound, dict);
    }
}
meJustAndrew
  • 6,011
  • 8
  • 50
  • 76
Debendra Dash
  • 5,334
  • 46
  • 38
11

Set this code (taken from http://www.c-sharpcorner.com/uploadfile/fc9f65/uploading-a-file-with-web-api-and-entity-framework-using-aja/) on the WEB API Post Controller:

    // POST: api/FileUploads
    [ResponseType(typeof(FileUpload))]
    public IHttpActionResult PostFileUpload()
    {
        if (HttpContext.Current.Request.Files.AllKeys.Any())
        {
            // Get the uploaded image from the Files collection  
            var httpPostedFile = HttpContext.Current.Request.Files["UploadedImage"];
            if (httpPostedFile != null)
            {
                FileUpload imgupload = new FileUpload();
                int length = httpPostedFile.ContentLength;
                imgupload.imagedata = new byte[length]; //get imagedata  
                httpPostedFile.InputStream.Read(imgupload.imagedata, 0, length);
                imgupload.imagename = Path.GetFileName(httpPostedFile.FileName);
                db.FileUploads.Add(imgupload);
                db.SaveChanges();
                // Make sure you provide Write permissions to destination folder
                string sPath = @"C:\Users\xxxx\Documents\UploadedFiles";
                var fileSavePath = Path.Combine(sPath, httpPostedFile.FileName);
                // Save the uploaded file to "UploadedFiles" folder  
                httpPostedFile.SaveAs(fileSavePath);
                return Ok("Image Uploaded");
            }
        }
        return Ok("Image is not Uploaded"); 
    }

On your UWP application, set the following method:

    using System;
    using System.Threading.Tasks;
    using Windows.Storage;
    using Windows.Storage.Streams;
    using Windows.Web.Http;
    // ...
    public static bool UploadImageToServer(StorageFile imageFile)
    {
        bool saveRes = false;
        try
        {
            using (HttpClient client = new HttpClient())
            {
                if (client != null) // if no Network Connection
                {
                    HttpResponseMessage response = new HttpResponseMessage();
                    Task task = Task.Run(async () =>
                    {
                        using (HttpMultipartFormDataContent formData = new HttpMultipartFormDataContent())
                        {
                            IBuffer buffer = await FileIO.ReadBufferAsync(imageFile);
                            HttpBufferContent WebHTTPContent = new HttpBufferContent(buffer);
                            formData.Add(WebHTTPContent, "UploadedImage", imageFile.Name);
                            response = await client.PostAsync(App.VehicleImageUri, formData);
                            if (response.IsSuccessStatusCode) saveRes = true;
                        }
                    });
                    task.Wait();
                }
            }
        }
        catch (Exception em)
        {
           // Handle exception here ... 
        }
        return saveRes;
    }

You call your method as follows:

private async void CaptureImageByUser()
{
    StorageFile file;

    // Create storage file in local app storage
    string fileName = GenerateNewFileName() + ".jpg";
    CreationCollisionOption collisionOption = CreationCollisionOption.GenerateUniqueName;

    file = await ApplicationData.Current.TemporaryFolder.CreateFileAsync(fileName, collisionOption);

    // Captures and stores new Jpeg image file
    await mediaCapture.CapturePhotoToStorageFileAsync(ImageEncodingProperties.CreateJpeg(), file);
    // Delete the file in the temporary location if successfully uploaded
    if (SaveDataByUser.UploadImageToServer(file)) await file.DeleteAsync();
}

private string GenerateNewFileName(string prefix = "IMG")
{
    return prefix + "_" + DateTime.UtcNow.ToString("yyyy-MMM-dd_HH-mm-ss");
}

Hey, let me know if it works for you!! Happy to help! :)

Hakan Fıstık
  • 16,800
  • 14
  • 110
  • 131
Manuel Hernandez
  • 581
  • 1
  • 7
  • 11
4

WebApi supports deserializing JSON array, so that you can receive bytes by declaring with byte[].

The following example will show how to upload image:

public class ImageModel
{
    public string Name { get; set; }
    public byte[] Bytes { get; set; }
}

In your controller. Writing image to disk:

private string WriteImage(byte[] arr)
{
    var filename = $@"images\{DateTime.Now.Ticks}.";

    using (var im = Image.FromStream(new MemoryStream(arr)))
    {
        ImageFormat frmt;
        if (ImageFormat.Png.Equals(im.RawFormat))
        {
            filename += "png";
            frmt = ImageFormat.Png;
        }
        else
        {
            filename += "jpg";
            frmt = ImageFormat.Jpeg;
        }
        string path = HttpContext.Current.Server.MapPath("~/") + filename;
        im.Save(path, frmt);
    }

    return $@"http:\\{Request.RequestUri.Host}\{filename}";
}

HttpContext.Current.Server.MapPath("~/") will give the internal path of server running. Request.RequestUri.Host returns the hostname.

public IHttpActionResult UploadImage(ImageModel model)
{
    var imgUrl = WriteImage(model.Bytes);

    // Some code
}

To send image from browser

In HTML:

<input type="file" id="imageFile"/>

Upload method for AngularJS:

$scope.upload = function () {

     var file = document.getElementById("imageFile").files[0];
     var r = new FileReader();
     r.onloadend = function (e) {


         var arr = Array.from(new Uint8Array(e.target.result));

         var uploadData = {
             Name: "Name of Image",
             Bytes: arr
         }
         console.log(uploadData);

         $http.post('api/Uploader/UploadImage', uploadData)
         .then(
         function (response) {
             console.log(response);
         },

         function (reason) {

             console.log(reason);
         })
     }
     r.readAsArrayBuffer(file);
 }
Hakan Fıstık
  • 16,800
  • 14
  • 110
  • 131
Orkhan Alikhanov
  • 9,122
  • 3
  • 39
  • 60
2

You can simply convert your image to a Base64String then post it as a StringContent.

public static async Task<T> Post<T>(string controller, string method, string accessToken, string bodyRequest) where T : class
{
    using (HttpClient client = new HttpClient())
    {
        client.DefaultRequestHeaders.Clear();
        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);

        var stringContent = new StringContent(bodyRequest, Encoding.UTF8, "application/json");

        var response = await client.PostAsync($"{Constants.ApiBaseUrl}/api/{controller}/{method}", stringContent);
        if (response.IsSuccessStatusCode)
            return response.Content as T;
    }
    return default(T);
}

bodyRequest on my code is the class/Model value to be converted to string

using Json.Serialize(model) which also contains your image System.Convert.ToBase64String(imageBytes[]) as its property.

Hakan Fıstık
  • 16,800
  • 14
  • 110
  • 131
pampi
  • 517
  • 4
  • 8
1

If your API only allows one image at a time, System.Web.Helpers.WebImage may help. Just make sure that a filename is included.

------WebKitFormBoundaryzrmNUJnUirtKajVF Content-Disposition: form-data; name="image"; filename="IMG_3321.JPG" Content-Type: image/jpeg

------WebKitFormBoundaryzrmNUJnUirtKajVF--

[HttpPost]
[ResponseType(typeof(Models.Photo))]
[Route("upload")]
public async Task<IHttpActionResult> Upload()
{
    var img = WebImage.GetImageFromRequest();
    if (img == null)
    {
        return BadRequest("Image is null.");
    }

    // Do whatever you want with the image (resize, save, ...)

    // In this case, I save the image to a cloud storage and
    // create a DB record to reference the image.
}
Hakan Fıstık
  • 16,800
  • 14
  • 110
  • 131
Kin
  • 1,522
  • 1
  • 13
  • 11
1

You Can Use This Sample To Upload Image In Web Api.

First create ImageWriterHelper to check the file format

  public class ImageWriterHelper
        {
            public enum ImageFormat
            {
                Bmp,
                Jpeg,
                Gif,
                Tiff,
                Png,
                Unknown
            }

        public static ImageFormat GetImageFormat(byte[] bytes)
        {
            var bmp = Encoding.ASCII.GetBytes("BM");
            var gif = Encoding.ASCII.GetBytes("GIF");
            var png = new byte[] { 137, 80, 78, 71 };
            var tiff = new byte[] { 73, 73, 42 };
            var tiff2 = new byte[] { 77, 77, 42 };
            var jpeg = new byte[] { 255, 216, 255, 224 };
            var jpeg2 = new byte[] { 255, 216, 255, 225 };

            if (bmp.SequenceEqual(bytes.Take(bmp.Length)))
                return ImageFormat.Bmp;

            if (gif.SequenceEqual(bytes.Take(gif.Length)))
                return ImageFormat.Gif;

            if (png.SequenceEqual(bytes.Take(png.Length)))
                return ImageFormat.Png;

            if (tiff.SequenceEqual(bytes.Take(tiff.Length)))
                return ImageFormat.Tiff;

            if (tiff2.SequenceEqual(bytes.Take(tiff2.Length)))
                return ImageFormat.Tiff;

            if (jpeg.SequenceEqual(bytes.Take(jpeg.Length)))
                return ImageFormat.Jpeg;

            if (jpeg2.SequenceEqual(bytes.Take(jpeg2.Length)))
                return ImageFormat.Jpeg;

            return ImageFormat.Unknown;
        }
        }

Then you should create class for saving image

  public class AddCandidateProfilePictureCommand:     
                                       IAddCandidateProfilePictureCommand
       {
        public AddCandidateProfilePictureResponse Execute(HttpPostedFile 
       postedFile)
        {
            byte[] fileBytes;

            using (var memoryStream = new MemoryStream())
            {
                postedFile.InputStream.CopyTo(memoryStream);
                fileBytes = memoryStream.ToArray();
            }

            if (ImageWriterHelper.GetImageFormat(fileBytes) == 
                ImageWriterHelper.ImageFormat.Unknown)
                throw new BadImageFormatException();

            var extension = Path.GetExtension(postedFile.FileName);
            var tempCandidateImageName = Guid.NewGuid();
            var fileName = $"{tempCandidateImageName}{extension}";
            var fileUrl =              
    WebConfigurationManager.AppSettings["CandidateProfilePictureAddress"];

            var filePath = Path.Combine(fileUrl, fileName);

            if (!Directory.Exists(fileUrl))
                Directory.CreateDirectory(fileUrl);

            postedFile.SaveAfterResizeImage(filePath, extension);

            return new AddCandidateProfilePictureResponse { 
                      TempCandidateImageName = fileName };
        }
        }

Next create class ImageResizeHelper to resize the image

 public static class ImageResizeHelper
        {
            public static void SaveAfterResizeImage( this HttpPostedFile 
                               postedFile,string filePath, string extension)
            {
                postedFile.SaveAs(filePath);

                var resizeSetting = new ResizeSettings
                {
                    Width = 500,
                    Height = 500,
                    Format = extension
                };

                ImageBuilder.Current.Build(filePath,ilePath,resizeSetting);
            }
        }

At the end create action In Controller

  [HttpPost]
        public IHttpActionResult AddCandidateProfilePicture()
        {
            var request = HttpContext.Current.Request;
            const int maxContentLength = 512 * 512 * 1;

            if (request.ContentLength > maxContentLength || 
                request.Files.Count == 0)
                return BadRequest();

            var pictureFile = request.Files[0];

            var result = 
AddCandidateProfilePictureCommand.Execute(pictureFile);

            return Ok(result);
        }

I Used constructor injection for creating an instance of classes

please see this link: Uploading Image To Server Using Web API 2.0

piet.t
  • 11,718
  • 21
  • 43
  • 52
Amin Golmahalleh
  • 3,585
  • 2
  • 23
  • 36