I'm trying to add the ability to upload zip files to a server. The client side is built with AngularJS, and the server side is C# ASP.NET, but I can't get it to work.
My server-side code looks like this:
[System.Web.Script.Services.ScriptService]
public class xyz : System.Web.Services.WebService
{
// Other WebMethods that work fine
[WebMethod]
public string UploadFile(byte[] file, string filename)
{
// do whatever
}
}
And I'm using ng-file-upload to attempt to do the actual upload. The HTML looks like:
<form>
<div class="form-group">
<label class="control-label h3" for="zipFile">Zip File</label>
<input class="form-control my-file" type="file" ngf-select ng-model="zipFile" id="zipFile" name="zipFile" accept=".zip" required />
</div>
<button class="btn btn-default" ng-click="submit()">Submit</button>
</form>
And the Javascript in my controller looks like this:
FileLoadController.$inject = ['$scope', 'Upload'];
function FileLoadController($scope, Upload) {
var vm = this;
vm.scope = $scope;
vm.scope.submit = function () {
if (vm.scope.zipFile) {
vm.scope.upload(vm.scope.zipFile);
}
}
vm.scope.upload = function (file) {
Upload.upload({
url: 'xyz.asmx/UploadFile',
data: { 'file': file, 'filename': file.name },
},
})
.then(function (response) {
alert(response);
});
}
}
Upload.upload gets called, but the UploadFile method on the server side is never executed.
It's probably something simple, but what am I doing wrong? Is there a better, or easier, way to do this?
Thank you.
I wound up not trying to use the existing WebHandler and added an IHttpHandler specifically for uploading. I didn't want to add a different handler, but whatever works.
There is an example referenced by ng-upload-file (ng-file-upload .NET example), but let me summarize what I did.
(Steps 1 & 2) adding the Generic Handler to the project creates a class derived from IHttpHandler, and it looks like this
public class UploadHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
if (context.Request.Files.Count > 0)
{
HttpFileCollection files = context.Request.Files;
for (int i = 0; i < files.Count; i++)
{
HttpPostedFile file = files[i];
string fname = context.Server.MapPath("uploads\\" + file.FileName);
file.SaveAs(fname);
// Do something with the file if you want
}
context.Response.Write("File/s uploaded successfully");
}
else
context.Response.Write("No files uploaded");
}
public bool IsReusable
{
get
{
return false;
}
}
}
(Step 3) Updating the AngularJS controller made it look like this
vm.scope.submit = function () {
if (vm.scope.zipFile) {
vm.scope.upload(vm.scope.zipFile);
}
}
vm.scope.upload = function (file) {
Upload.upload({
url: 'UploadHandler.ashx',
data: { },
file: file
})
.then(function (response) {
alert(response.data);
})
}
(Step 4) Added ngf-max-size so files up to 1GB can be uploaded
<form>
<div class="form-group">
<label class="control-label h3" for="zipFile">Zip File</label>
<input class="form-control my-file" type="file" ngf-select ng-model="zipFile" id="zipFile" name="zipFile" ngf-max-size="1GB" accept=".zip" required />
</div>
<button class="btn btn-default" ng-click="submit()">Submit</button>
</form>
(Step 5) Then I had to tweak the web.config file to allow those large files. It involved adding two things. The first was maxRequestLength added to the httpRuntime, like so:
<configuration>
<!--Lots of omitted stuff-->
<system.web>
<httpRuntime targetFramework="4.5.1" maxRequestLength="1073741824" />
</system.web>
</configuration>
The second was to add a security section so large things wouldn't be filtered out:
<configuration>
<!--Lots more omitted stuff-->
<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="1073741824"/>
</requestFiltering>
</security>
</system.webServer>
</configuration>