Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET WEBAPI file upload, issues with IE9

I have created a file upload method using ASP.NET WEBAPI, below the code:

[DataContract]
    public class FileDesc
    {
        [DataMember]
        public string name { get; set; }      

        [DataMember]
        public string url { get; set; }

        [DataMember]
        public long size { get; set; }

        [DataMember]
        public string UniqueFileName { get; set; }

        [DataMember]
        public int id { get; set; }

        [DataMember]
        public DateTime modifiedon { get; set; }

        [DataMember]
        public string description { get; set; }


        public FileDesc(string rootUrl, FileInfo f,int pId, string aFileName)
        {
            id = pId;
            name = aFileName;
            UniqueFileName = f.Name;
            url = rootUrl + "/Files/" + f.Name;
            size = f.Length / 1024;
            modifiedon = f.LastWriteTime;
            description = aFileName;
        }
    }

    public class CustomMultipartFormDataStreamProvider : MultipartFormDataStreamProvider
    {
        //string uniqueFileName = string.Empty;

        public string UniqueFileName
        {
            get;
            set;
        }
        public string ActualFileName
        {
            get;
            set;
        }

        public int TaskID { get; set; }
        private int UserID { get; set; }
        public CustomMultipartFormDataStreamProvider(string path, int ptaskID, int pUserID)
            : base(path)
        {
            TaskID = ptaskID;
            UserID = pUserID;
        }

        public override string GetLocalFileName(System.Net.Http.Headers.HttpContentHeaders headers)
        {
            var name = !string.IsNullOrWhiteSpace(headers.ContentDisposition.FileName) ? headers.ContentDisposition.FileName : "NoName";

            ActualFileName = name.Replace("\"", string.Empty);

            ActualFileName = Path.GetFileName(ActualFileName);

            UniqueFileName = Guid.NewGuid().ToString() + Path.GetExtension(ActualFileName);

            int id = SaveFileInfoIntoDatabase(ActualFileName, TaskID, UniqueFileName, UserID);

            headers.Add("ActualFileName", ActualFileName);
            headers.Add("id", id.ToString());

            return UniqueFileName;

        }   
    }
    [Authorize]
    public class FileUploadController : ApiController
    {

        private string StorageRoot
        {
            get { return Path.Combine(System.Web.HttpContext.Current.Server.MapPath("~/Files/")); } //Path should! always end with '/'
        }


        public Task<IEnumerable<FileDesc>> Post(int id)        
        {

            string folderName = "Files";
            string PATH = HttpContext.Current.Server.MapPath("~/" + folderName);
            string rootUrl = Request.RequestUri.AbsoluteUri.Replace(Request.RequestUri.AbsolutePath, String.Empty);
            HttpContext.Current.Response.BufferOutput = true;
            HttpContext.Current.Response.Buffer = true;
            HttpContext.Current.Response.ContentType = "text/html";

            if (Request.Content.IsMimeMultipartContent())
            {
                var streamProvider = new CustomMultipartFormDataStreamProvider(PATH, id, BEL_PMS.Utilities.FormsAuthenticationUtil.GetCurrentUserID);
                var task = Request.Content.ReadAsMultipartAsync(streamProvider).ContinueWith<IEnumerable<FileDesc>>(t =>
                {

                    if (t.IsFaulted || t.IsCanceled)
                    {
                        throw new HttpResponseException(HttpStatusCode.InternalServerError);
                    }

                    var fileInfo = streamProvider.FileData.Select(i =>
                    {

                        var info = new FileInfo(i.LocalFileName);
                        int FileID = Convert.ToInt32((from h in i.Headers where h.Key =="id" select h.Value.First()).FirstOrDefault());
                        string ActualFileName = (from h in i.Headers where h.Key =="ActualFileName" select h.Value.First()).FirstOrDefault();
                        return new FileDesc(rootUrl, info, FileID, ActualFileName);
                    });
                    return fileInfo;
                });


                //return new HttpResponseMessage { StatusCode = System.Net.HttpStatusCode.OK, Content = task};               
                return task;
            }
            else
            {
                throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotAcceptable, "This request is not properly formatted"));
            }

        }
}

and uploading files via Ajax using jquery.form.js plugin, below is the code:

$('#frmmultiupload').ajaxForm({
            success: OnUploadedSuccessfully,            
            error: function (x, y) {
                mesg('Error occured while file upload! Please make sure that total file size is less than 4 MB and try again.',
                    'error', 'File upload failed.');
            }
        });

everything works file but it is creating problem in IE9

IE says "Do you want to open or save from local host?"

enter image description here Below is the network trace: enter image description here I found some hint here not don't know how to convert Task<IEnumerable<FileDesc>> to Task<HttpResponseMessage>.

I have specified timeout of 30 sec in ajaxSetup, so after 30 sec it is generating error.

like image 599
Vipul Avatar asked Feb 19 '23 08:02

Vipul


2 Answers

var task = Request.Content.ReadAsMultipartAsync(streamProvider).ContinueWith<HttpResponseMessage>(t =>
{
    if (t.IsFaulted || t.IsCanceled)
    {
        throw new HttpResponseException(HttpStatusCode.InternalServerError);
    }

    var fileInfo = streamProvider.FileData.Select(i =>
    {

        var info = new FileInfo(i.LocalFileName);
        int FileID = Convert.ToInt32((from h in i.Headers where h.Key =="id" select h.Value.First()).FirstOrDefault());
        string ActualFileName = (from h in i.Headers where h.Key =="ActualFileName" select h.Value.First()).FirstOrDefault();
        return new FileDesc(rootUrl, info, FileID, ActualFileName);
    });
    var response = Request.CreateResponse(HttpStatusCode.OK, fileInfo);
    response.Content.Headers.ContentType = new MediaTypeHeaderValue("text/html");
    return response;
});
like image 59
Vipul Avatar answered Feb 21 '23 02:02

Vipul


IE 9 does not support the new XMLHttpRequest Level 2 (only IE10+), which means that the jquery.form.js plug-in uses the iframe fallback. Read this: http://www.malsup.com/jquery/form/#file-upload posted by the creator of the jquery.form.js plug-in. He states there that IE will prompt for a download if the return data is JSON or Script. Jou have to force the content-type header to "text/html" if you return JSON.

like image 36
Francois Grobler Avatar answered Feb 21 '23 02:02

Francois Grobler