Javascript ASP.NET AJAX AjaxFileUpload:引发上载完成事件并启动新上载的未捕获错误

Javascript ASP.NET AJAX AjaxFileUpload:引发上载完成事件并启动新上载的未捕获错误,javascript,file-upload,multifile-uploader,scriptresource.axd,Javascript,File Upload,Multifile Uploader,Scriptresource.axd,我在我的web应用程序中添加了一个AJAX多文件上载控件。当我尝试上载多个文件时,仅上载第一个文件,Chrome开发控制台中显示以下错误: 引发上载完成事件并启动新上载的未捕获错误 我的控制: JavaScript: function MultiUploadComplete(sender, args) { var filesize = args.get_fileSize(); var fileId = args.get_fileId(); var status = do

我在我的web应用程序中添加了一个AJAX多文件上载控件。当我尝试上载多个文件时,仅上载第一个文件,Chrome开发控制台中显示以下错误:

引发上载完成事件并启动新上载的未捕获错误

我的控制:

JavaScript:

function MultiUploadComplete(sender, args) {
    var filesize = args.get_fileSize();
    var fileId = args.get_fileId();
    var status = document.getElementById('multiUploader_FileItemStatus_' + fileId);
    var container = document.getElementById('multiUploader_FileInfoContainer_' + fileId);
    var fileName = $(container).find('span.filename').html();

    if (filesize > 10240000) { 
        fileErrors += 1;
        if (status.innerText) {
            status.innerText = " (Error) " + $('#profilephotosize').attr('data-val').replace('{0}', fileName);
        }
        if (status.textContent) {
            status.textContent = " (Error) " + $('#profilephotosize').attr('data-val').replace('{0}', fileName);
        }
        container.style.color = 'Red';
    }
}

function AllUploaded() {
    if (fileErrors > 0) {
        alert($('#filesnotuploaded').attr('data-val').replace('{0}', fileErrors));
    }
    ShowData();
}
后端代码:

   Private Function ResizeAndSaveImage(ByVal maxWidth As Integer, ByVal maxHeight As Integer, ByVal path As String, ByVal img As Image) As Boolean
        'scale the image to maxWidth and maxHeight
        'save image
        Dim newWidth, newHeight As Integer
        Dim scaleFactor As Double
        Dim bResult As Boolean

        newWidth = img.Width
        newHeight = img.Height

        If img.Width > maxWidth Or img.Height > maxHeight Then
            If img.Width > maxWidth Then
                scaleFactor = maxWidth / img.Width
                newWidth = Math.Round(img.Width * scaleFactor, 0)
                newHeight = Math.Round(img.Height * scaleFactor, 0)
            End If
            If newHeight > maxHeight Then
                scaleFactor = maxHeight / newHeight
                newWidth = Math.Round(newWidth * scaleFactor, 0)
                newHeight = Math.Round(newHeight * scaleFactor, 0)
            End If
        End If


        'code below copied from: http://www.webcosmoforums.com/asp/321-create-high-quality-thumbnail-resize-image-dynamically-asp-net-c-code.html
        Try
            Dim bmp As New Bitmap(newWidth, newHeight)

            Dim gr As System.Drawing.Graphics = System.Drawing.Graphics.FromImage(bmp)
            gr.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality
            gr.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality
            gr.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High

            Dim rectDestination As New System.Drawing.Rectangle(0, 0, newWidth, newHeight)
            gr.DrawImage(img, rectDestination, 0, 0, img.Width, img.Height,
             GraphicsUnit.Pixel)

            bmp.Save(path)


            System.IO.File.WriteAllBytes(ChangeExtension(path, "webp"), imageFunctions.EncodeImageToWebP(bmp))


            bmp.Dispose()
            bResult = True

        Catch ex As Exception

        End Try

        Return bResult
    End Function


    Protected Sub afuPhoto_UploadedComplete(ByVal sender As Object, ByVal e As AjaxControlToolkit.AsyncFileUploadEventArgs)
        Dim afuPhoto As AjaxControlToolkit.AsyncFileUpload = CType(sender, AjaxControlToolkit.AsyncFileUpload)

        Dim pageId As Integer = 9

        If ConfigurationManager.AppSettings("isDevelopment") = "false" Then
            pageId = 1
        End If

        Dim allowedPhotos As Integer = ConfigurationManager.AppSettings("page_photos")

        Dim TA As New mysiteTableAdapters.sitephotoalbumsTableAdapter
        Dim totalPhotos As Integer = TA.CountPhotosForPageId(pageId)

        Session("pageid") = pageId
        'ReportError("afuPhoto_UploadedComplete.pageId", pageId.ToString)

        If totalPhotos >= allowedPhotos Then
            Exit Sub
        End If

        'code by mitsbits
        If afuPhoto.HasFile AndAlso e.State = AjaxControlToolkit.AsyncFileUploadState.Success Then

            'only if images are from same location, have same name and are uploaded at time calculated below a conflict could arise...chance minimal!
            Dim d As String = (DateTime.Now.Millisecond + DateTime.Now.Second).ToString

            If UploadFile(afuPhoto, pageId, d) = GlobalFunctions.ResultType.Success Then
                'if file upload successfull update database with photo
                TA.Insert(pageId, pageId.ToString + "_" + d + "_" + MakeValidImageName(afuPhoto.FileName), DateTime.Now)
            End If

        End If


    End Sub

    Protected Function UploadFile(ByVal FU As AjaxControlToolkit.AsyncFileUpload, ByVal locationId As Integer, ByVal curdate As String) As GlobalFunctions.ResultType
        Dim filename As String = MakeValidImageName(FU.PostedFile.FileName)
        Dim result As GlobalFunctions.ResultType
        Dim thumbgalleryPath, galleryPath, largethumbgalleryPath As String
        galleryPath = ConfigurationManager.AppSettings("page_photospath").ToString
        thumbgalleryPath = ConfigurationManager.AppSettings("page_thumbsphotospath").ToString
        largethumbgalleryPath = ConfigurationManager.AppSettings("page_largethumbsphotospath").ToString


        If FU.PostedFile.FileName IsNot Nothing And FU.PostedFile.ContentLength > 0 Then
            If FU.PostedFile.ContentLength <= 10240000 Then '10MB
                If Not filename.ToLower.Contains(".jpg") And Not filename.ToLower.Contains(".png") And Not filename.ToLower.Contains(".gif") And Not filename.ToLower.Contains(".jpeg") Then
                    Return ResultType.notallowed
                End If

                Dim imgOriginal As Image = System.Drawing.Image.FromStream(FU.PostedFile.InputStream)
                Dim imgOriginal1 As Image = imgOriginal 'this image is used as image is disposed

                'save large image and save thumb image
                If ResizeAndSaveImage(1200, 1200, Server.MapPath(galleryPath) + locationId.ToString + "_" + curdate + "_" + MakeValidImageName(filename), imgOriginal) And
                    ResizeAndSaveImage(450, 400, Server.MapPath(largethumbgalleryPath) + locationId.ToString + "_" + curdate + "_" + MakeValidImageName(filename), imgOriginal) And
                    ResizeAndSaveImage(75, 75, Server.MapPath(thumbgalleryPath) + locationId.ToString + "_" + curdate + "_" + MakeValidImageName(filename), imgOriginal) Then
                    result = ResultType.Success
                End If

                imgOriginal.Dispose()
            End If
        End If

        If Not result = GlobalFunctions.ResultType.Success Then
            'upload failed rollback
            GlobalFunctions.DeleteFile(Server.MapPath(galleryPath) + locationId.ToString + "_" + filename)
            GlobalFunctions.DeleteFile(Server.MapPath(largethumbgalleryPath) + locationId.ToString + "_" + filename)
            GlobalFunctions.DeleteFile(Server.MapPath(thumbgalleryPath) + locationId.ToString + "_" + filename)
        End If

        Return result
    End Function


    Protected Sub multiUploader_UploadComplete(sender As Object, e As AjaxControlToolkit.AjaxFileUploadEventArgs) 'Handles multiUploader.UploadComplete
        'check if the postback control was the linkbutton 'Opslaan', if it is, abort the upload function
        'Dim ctrlname As String = Page.Request.Params.Get("__EVENTTARGET") 'PS. this code does NOT work when checking for postbacks with BUTTON controls
        'If ctrlname.ToString <> "" AndAlso (ctrlname.Contains("btnSaveProfile") Or ctrlname.Contains("lbtnSetCoverPhoto")) Then 'save location button was clicked
        '    Exit Sub
        'End If
        'ReportError("multiUploader_UploadComplete")

        Dim pageId = 1

        Dim TAphotos As New mysiteTableAdapters.sitephotoalbumsTableAdapter
        Dim DTphotos As mysite.sitephotoalbumsDataTable = TAphotos.GetPagePhotos(pageId)


        Dim allowedPhotos As Integer = ConfigurationManager.AppSettings("page_photos")

        Dim totalPhotos As Integer = DTphotos.Rows.Count

        If totalPhotos >= allowedPhotos Then Exit Sub

        'code by mitsbits
        If e.State = AjaxControlToolkit.AjaxFileUploadState.Success Then 'multiUploader.afuPhoto.HasFile AndAlso

            'only if images are from same location, have same name and are uploaded at time calculated below a conflict could arise...chance minimal!
            'Dim d As String = (DateTime.Now.Millisecond + DateTime.Now.Second).ToString
            Dim d As String = DateTime.Now.Second.ToString + "_" + DateTime.Now.Millisecond.ToString
            Dim imageWidth, imageHeight As Integer



            If e.FileSize > 10240000 Then
                ScriptManager.RegisterClientScriptBlock(Me, Me.GetType(), "newfile",
    "alert('file too large');", True)

                Exit Sub
            End If

            'ReportError("e.filename", e.FileName.ToString)

            Dim result As GlobalFunctions.ResultType = UploadMultiFile(System.Drawing.Image.FromStream(e.GetStreamContents), e.FileName, pageId, d, imageWidth, imageHeight)
            If result = GlobalFunctions.ResultType.Success Then
                'if file upload successfull update database with photo
                Dim returnval As Integer

                'Dim clientIPAddress As String = Request.ServerVariables("REMOTE_ADDR").ToString

                returnval = TAphotos.Insert(pageId, pageId.ToString + "_" + d + "_" + MakeValidImageName(e.FileName), DateTime.Now)



            ElseIf result = ResultType.invalidtype Then


                '            '            ScriptManager.RegisterClientScriptBlock(Me, Me.GetType(), "newfile",
                '            '"window.parent.$find('" + multiUploader.ClientID + "').newFileName='invalidfiletype';", True)
                '            Try
                '                ScriptManager.RegisterClientScriptBlock(Me, Me.GetType(), "newfile",
                '"window.parent.$find('" + CType(dvSitePage.FindControl("multiUploader"), AjaxControlToolkit.AjaxFileUpload).ClientID + "').newFileName='invalidfiletype';", True)

                '            Catch ex As Exception

                '            End Try


            End If


        End If

    End Sub


    Protected Function UploadMultiFile(ByVal imgOriginal As Image, ByVal fileName As String, ByVal pageId As Integer, ByVal curdate As String, ByRef imageWidth As Integer, ByRef imageHeight As Integer) As GlobalFunctions.ResultType
        fileName = MakeValidImageName(fileName)
        Dim result As GlobalFunctions.ResultType
        Dim thumbgalleryPath, origgalleryPath, photopathMedium As String

        origgalleryPath = ConfigurationManager.AppSettings("page_photospath").ToString
        photopathMedium = ConfigurationManager.AppSettings("page_largethumbsphotospath").ToString
        thumbgalleryPath = ConfigurationManager.AppSettings("page_thumbsphotospath").ToString


        Dim imgOriginal1 As Image = imgOriginal 'this image is used as image is disposed

        'save large image and save thumb image
        If ResizeAndSaveImage(1200, 1200, Server.MapPath(origgalleryPath) + pageId.ToString + "_" + curdate + "_" + fileName, imgOriginal) And', imageWidth, imageHeight
            ResizeAndSaveImage(190, 190, Server.MapPath(photopathMedium) + pageId.ToString + "_" + curdate + "_" + fileName, imgOriginal) And
            ResizeAndSaveImage(75, 75, Server.MapPath(thumbgalleryPath) + pageId.ToString + "_" + curdate + "_" + fileName, imgOriginal) Then
            result = ResultType.Success
        End If


        imgOriginal.Dispose()



        If Not result = GlobalFunctions.ResultType.Success Then
            'upload failed rollback
            GlobalFunctions.DeleteFile(Server.MapPath(origgalleryPath) + pageId.ToString + "_" + fileName)
            GlobalFunctions.DeleteFile(Server.MapPath(thumbgalleryPath) + pageId.ToString + "_" + fileName)
            GlobalFunctions.DeleteFile(Server.MapPath(photopathMedium) + pageId.ToString + "_" + fileName)

            GlobalFunctions.DeleteFile(IO.Path.ChangeExtension(Server.MapPath(origgalleryPath) + pageId.ToString + "_" + fileName, "webp"))
            GlobalFunctions.DeleteFile(IO.Path.ChangeExtension(Server.MapPath(thumbgalleryPath) + pageId.ToString + "_" + fileName, "webp"))
            GlobalFunctions.DeleteFile(IO.Path.ChangeExtension(Server.MapPath(photopathMedium) + pageId.ToString + "_" + fileName, "webp"))
        Else
            'update successfull
        End If

        Return result
    End Function

500错误表示向web服务器发出了请求,但它无法处理该请求。要找到根本原因很难,因为问题可能是前端、后端、环境(web.config/app pool settings)或DevExpress的问题

因此,您应该单独运行代码。例如:创建一个空白的aspx页面(无母版页),其中包含AjaxFileUpload,并具有空函数/方法。如果可行,则添加最短代码以保存图像(到临时文件夹)。如果这样做有效,则逐位复制代码,直到可以创建错误为止

或者在后端代码中添加一些日志记录。看起来您有一个try/catch来隐藏异常。如果有错误,那么变量结果将返回为null。看起来MultiUploadComplete()并没有检查是否成功,只是检查文件的大小

或者,重新写入AjaxFileUpload。它没有得到很好的支持,现代JavaScript、HTML和web浏览器意味着它更容易实现

看一看。本文展示了如何使用纯JavaScript、HTML5创建一个多文件拖放上传程序。您需要创建一个端点,最好使用WebApi或通用处理程序(如果使用较旧版本的asp.net)

作为概念的简单证明。我创建了一个aspx页面,将图像发布到api。它一次单独发送文件以提高性能(但您可以在一个请求中完成所有操作)。需要指出的主要问题是,没有第三方库,您可以灵活地更改文件上传器的外观

ASPX代码

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="default.aspx.cs" Inherits="WebForms._default" %>

<!DOCTYPE html>
<html lang="en">
    <head runat="server">
        <title></title>
    </head>
    <body>
        <form id="form1" runat="server">
            <div id="drop-area">
            <p>Drop files here</p>
            <input type="file" id="fileElem" multiple accept="image/*" onchange="handleFiles(this.files)">
            <label class="button" for="fileElem">Select files</label>
            <progress id="progress-bar" max=100 value=0></progress>
            <div id="gallery" /></div>
            <input id="btnUpload" type="submit" value="Upload" />    
        </form> 
        <script type="text/javascript">     
            let btnUpload = document.getElementById("btnUpload")
            btnUpload.addEventListener('click', uploadFiles, false)

            function uploadFiles(event) {
                event.preventDefault();
                // TODO - validate file size, extension & amount

                files = [...fileElem.files]
                // Submit each file separately.
                files.forEach(uploadFile)
            }

            // This all copy & paste
            // ************************ Drag and drop ***************** //
            let dropArea = document.getElementById("drop-area")

                // Prevent default drag behaviors
                ;['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
                    dropArea.addEventListener(eventName, preventDefaults, false)
                    document.body.addEventListener(eventName, preventDefaults, false)
                })

                // Highlight drop area when item is dragged over it
                ;['dragenter', 'dragover'].forEach(eventName => {
                    dropArea.addEventListener(eventName, highlight, false)
                })

                ;['dragleave', 'drop'].forEach(eventName => {
                    dropArea.addEventListener(eventName, unhighlight, false)
                })

            // Handle dropped files
            dropArea.addEventListener('drop', handleDrop, false)

            function preventDefaults(e) {
                e.preventDefault()
                e.stopPropagation()
            }

            function highlight(e) {
                dropArea.classList.add('highlight')
            }

            function unhighlight(e) {
                dropArea.classList.remove('active')
            }

            function handleDrop(e) {
                var dt = e.dataTransfer
                var files = dt.files

                handleFiles(files)
            }

            let uploadProgress = []
            let progressBar = document.getElementById('progress-bar')

            function initializeProgress(numFiles) {
                progressBar.value = 0
                uploadProgress = []

                for (let i = numFiles; i > 0; i--) {
                    uploadProgress.push(0)
                }
            }

            function updateProgress(fileNumber, percent) {
                uploadProgress[fileNumber] = percent
                let total = uploadProgress.reduce((tot, curr) => tot + curr, 0) / uploadProgress.length
                //console.log('update', fileNumber, percent, total)
                progressBar.value = total
                return total === 100; 
            }

            function handleFiles(files) {
                files = [...files]
                initializeProgress(files.length)
                //files.forEach(uploadFile)
                files.forEach(previewFile)
            }

            function previewFile(file) {
                let reader = new FileReader()
                reader.readAsDataURL(file)
                reader.onloadend = function () {
                    let img = document.createElement('img')
                    img.src = reader.result
                    document.getElementById('gallery').appendChild(img)
                }
            }

            function uploadFile(file, i) {
                var url = '/api/UploadFile' // TODO: change end point
                var xhr = new XMLHttpRequest()
                var formData = new FormData()
                xhr.open('POST', url, true)
                xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest')

                // Update progress (can be used to show progress indicator)
                xhr.upload.addEventListener("progress", function (e) {
                    updateProgress(i, (e.loaded * 100.0 / e.total) || 100)
                })

                xhr.addEventListener('readystatechange', function (e) {
                    if (xhr.readyState == 4 && xhr.status == 200) {
                        if (updateProgress(i, 100)) {
                            alert('Complete') // TODO
                        }
                    }
                    else if (xhr.readyState == 4 && xhr.status != 200) {
                        alert('error') // TODO
                    }
                })

                formData.append('file', file)
                xhr.send(formData)
            }
        </script>

        <style type="text/css">
        body {
            font-family: sans-serif;
        }
        a {
            color: #369;
        }
        .note {
            width: 500px;
            margin: 50px auto;
            font-size: 1.1em;
            color: #333;
            text-align: justify;
        }
        #drop-area {
            border: 2px dashed #ccc;
            border-radius: 20px;
            width: 480px;
            margin: 50px auto;
            padding: 20px;
        }
        #drop-area.highlight {
            border-color: purple;
        }
        p {
            margin-top: 0;
        }
        .my-form {
            margin-bottom: 10px;
        }
        #gallery {
            margin-top: 10px;
        }
        #gallery img {
            width: 150px;
            margin-bottom: 10px;
            margin-right: 10px;
            vertical-align: middle;
        }
        .button {
            display: inline-block;
            padding: 10px;
            background: #ccc;
            cursor: pointer;
            border-radius: 5px;
            border: 1px solid #ccc;
        }
        .button:hover {
            background: #ddd;
        }
        #fileElem {
            display: none;
        }
    </style>
    </body>
</html>

把文件放在这里

选择文件 让btnUpload=document.getElementById(“btnUpload”) btnUpload.addEventListener('click',uploadFiles,false) 函数上载文件(事件){ event.preventDefault(); //TODO-验证文件大小、扩展名和数量 files=[…fileElem.files] //分别提交每个文件。 files.forEach(上传文件) } //这一切都是复制粘贴 //*******************************拖放**************************// 让dropArea=document.getElementById(“dropArea”) //防止默认拖动行为 ;['dragenter','dragover','dragleave','drop'].forEach(eventName=>{ dropArea.addEventListener(eventName、PreventDefault、false) document.body.addEventListener(eventName、PreventDefault、false) }) //当项目拖动到拖放区域上时,高亮显示该区域 ;['dragenter','dragover'].forEach(eventName=>{ dropArea.addEventListener(eventName、highlight、false) }) ;['dragleave','drop'].forEach(eventName=>{ dropArea.addEventListener(eventName、unhighlight、false) }) //处理丢弃的文件 dropArea.addEventListener('drop',handleDrop,false) 功能默认值(e){ e、 预防默认值() e、 停止传播() } 功能突出显示(e){ dropArea.classList.add('highlight') } 功能取消高亮度(e){ dropArea.classList.remove('active') } 函数handleDrop(e){ var dt=数据传输 var files=dt.files 手文件(文件) } 让uploadProgress=[] 让progressBar=document.getElementById('progress-bar') 函数初始化进程(numFiles){ progressBar.value=0 上传进度=[] 对于(设i=numFiles;i>0;i--){ 上载进度。推送(0) } } 函数updateProgress(文件号,百分比){ 上载进度[文件号]=百分比 让total=上传进度。reduce((tot,curr)=>tot+curr,0)/uploadProgress.length //console.log('update',fileNumber,percent,total) progressBar.value=总计 返回总数===100; } 函数句柄文件(文件){ 文件=[…文件] initializeProgress(files.length) //files.forEach(上传文件) files.forEach(预览文件) } 函数预览文件(文件){ let reader=new FileReader() reader.readAsDataURL(文件) reader.onloadend=函数(){ 设img=document.createElement('img') img.src=reader.result document.getElementById('gallery').appendChild(img) } } 函数上载文件(文件,i){ var url='/api/UploadFile'//TODO:更改端点 var xhr=newXMLHttpRequest() var formData=new formData() xhr.open('POST',url,true) setRequestHeader('X-Requested-With','XMLHttpRequest') //更新进度(可用于显示进度指示器) upload.addEventListener(“p
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="default.aspx.cs" Inherits="WebForms._default" %>

<!DOCTYPE html>
<html lang="en">
    <head runat="server">
        <title></title>
    </head>
    <body>
        <form id="form1" runat="server">
            <div id="drop-area">
            <p>Drop files here</p>
            <input type="file" id="fileElem" multiple accept="image/*" onchange="handleFiles(this.files)">
            <label class="button" for="fileElem">Select files</label>
            <progress id="progress-bar" max=100 value=0></progress>
            <div id="gallery" /></div>
            <input id="btnUpload" type="submit" value="Upload" />    
        </form> 
        <script type="text/javascript">     
            let btnUpload = document.getElementById("btnUpload")
            btnUpload.addEventListener('click', uploadFiles, false)

            function uploadFiles(event) {
                event.preventDefault();
                // TODO - validate file size, extension & amount

                files = [...fileElem.files]
                // Submit each file separately.
                files.forEach(uploadFile)
            }

            // This all copy & paste
            // ************************ Drag and drop ***************** //
            let dropArea = document.getElementById("drop-area")

                // Prevent default drag behaviors
                ;['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
                    dropArea.addEventListener(eventName, preventDefaults, false)
                    document.body.addEventListener(eventName, preventDefaults, false)
                })

                // Highlight drop area when item is dragged over it
                ;['dragenter', 'dragover'].forEach(eventName => {
                    dropArea.addEventListener(eventName, highlight, false)
                })

                ;['dragleave', 'drop'].forEach(eventName => {
                    dropArea.addEventListener(eventName, unhighlight, false)
                })

            // Handle dropped files
            dropArea.addEventListener('drop', handleDrop, false)

            function preventDefaults(e) {
                e.preventDefault()
                e.stopPropagation()
            }

            function highlight(e) {
                dropArea.classList.add('highlight')
            }

            function unhighlight(e) {
                dropArea.classList.remove('active')
            }

            function handleDrop(e) {
                var dt = e.dataTransfer
                var files = dt.files

                handleFiles(files)
            }

            let uploadProgress = []
            let progressBar = document.getElementById('progress-bar')

            function initializeProgress(numFiles) {
                progressBar.value = 0
                uploadProgress = []

                for (let i = numFiles; i > 0; i--) {
                    uploadProgress.push(0)
                }
            }

            function updateProgress(fileNumber, percent) {
                uploadProgress[fileNumber] = percent
                let total = uploadProgress.reduce((tot, curr) => tot + curr, 0) / uploadProgress.length
                //console.log('update', fileNumber, percent, total)
                progressBar.value = total
                return total === 100; 
            }

            function handleFiles(files) {
                files = [...files]
                initializeProgress(files.length)
                //files.forEach(uploadFile)
                files.forEach(previewFile)
            }

            function previewFile(file) {
                let reader = new FileReader()
                reader.readAsDataURL(file)
                reader.onloadend = function () {
                    let img = document.createElement('img')
                    img.src = reader.result
                    document.getElementById('gallery').appendChild(img)
                }
            }

            function uploadFile(file, i) {
                var url = '/api/UploadFile' // TODO: change end point
                var xhr = new XMLHttpRequest()
                var formData = new FormData()
                xhr.open('POST', url, true)
                xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest')

                // Update progress (can be used to show progress indicator)
                xhr.upload.addEventListener("progress", function (e) {
                    updateProgress(i, (e.loaded * 100.0 / e.total) || 100)
                })

                xhr.addEventListener('readystatechange', function (e) {
                    if (xhr.readyState == 4 && xhr.status == 200) {
                        if (updateProgress(i, 100)) {
                            alert('Complete') // TODO
                        }
                    }
                    else if (xhr.readyState == 4 && xhr.status != 200) {
                        alert('error') // TODO
                    }
                })

                formData.append('file', file)
                xhr.send(formData)
            }
        </script>

        <style type="text/css">
        body {
            font-family: sans-serif;
        }
        a {
            color: #369;
        }
        .note {
            width: 500px;
            margin: 50px auto;
            font-size: 1.1em;
            color: #333;
            text-align: justify;
        }
        #drop-area {
            border: 2px dashed #ccc;
            border-radius: 20px;
            width: 480px;
            margin: 50px auto;
            padding: 20px;
        }
        #drop-area.highlight {
            border-color: purple;
        }
        p {
            margin-top: 0;
        }
        .my-form {
            margin-bottom: 10px;
        }
        #gallery {
            margin-top: 10px;
        }
        #gallery img {
            width: 150px;
            margin-bottom: 10px;
            margin-right: 10px;
            vertical-align: middle;
        }
        .button {
            display: inline-block;
            padding: 10px;
            background: #ccc;
            cursor: pointer;
            border-radius: 5px;
            border: 1px solid #ccc;
        }
        .button:hover {
            background: #ddd;
        }
        #fileElem {
            display: none;
        }
    </style>
    </body>
</html>
using System;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Http;

namespace WebForms.Controllers
{
    public class UploadFilesController : ApiController
    {
        [Route("api/UploadFile/")]
        public IHttpActionResult UploadFile()
        {
            var httpRequest = HttpContext.Current.Request;
           
            if (ValidateImage(httpRequest.Files))
            {
                var file = httpRequest.Files[0];
                var fileName = Path.GetFileName(file.FileName);
                var filePath = HttpContext.Current.Server.MapPath($"~/{fileName}");
               
                SaveImage(file, filePath);
                return Ok();
            }
            else
            {
                return BadRequest();
            }            
        }

        private void SaveImage(HttpPostedFile file, string filePath)
        {
            using (var sourceimage = Image.FromStream(file.InputStream))
            {
                sourceimage.Save(filePath);
            }
        }
            
        private bool ValidateImage(HttpFileCollection files)
        {
            return IsSingleFile(files)
            && IsValidFileType(files[0].FileName, files[0].ContentType)
            && IsValidSize(files[0].ContentLength);
        }

        public bool IsSingleFile(HttpFileCollection files)
        {
            return files.Count == 1;
        }

        public bool IsValidFileType(string fileName, string contentType)
        {
            string[] extensions = { "jpg", "jpeg", "gif", "bmp", "png" };
            return extensions.Any(extension => $"image/{extension}".Equals(contentType, StringComparison.OrdinalIgnoreCase))
            && extensions.Any(extension => $".{extension}".Equals(Path.GetExtension(fileName.ToLower()), StringComparison.OrdinalIgnoreCase));
        }

        public bool IsValidSize(int contentLength)
        {
            return contentLength < 2100000; // 2MBs
        }        
    }
}