Мой пример работает только с одним файлом. Мне нужен массив файлов. Я использую angularJS 1.7 и asp.net-core 2.0.
HTML
<div class = "post">
<form>
<textarea ng-model = "Headline" name = "Headline" rows = "2" cols = "63" class = "form-control"></textarea>
<textarea ng-model = "BodyText" name = "BodyText" rows = "4" cols = "63" class = "form-control"></textarea>
<input type = "file" file-model = "myFile" multiple/>
<input id = "Submit" class = "btn btn-default" ng-click = "createPost()" type = "submit" value = "Пост" />
</form>
</div>
Метод creatPost в контроллере AgularJs
$scope.createPost = function () {
var model = {
Headline: $scope.Headline,
BodyText: $scope.BodyText,
ImgPost: $scope.myFile
}
$http({
method: 'POST',
url: '/api/Blog/create-post/',
headers: {
'Content-Type': undefined
},
data: model,
transformRequest: function (data, headersGetter) {
var formData = new FormData();
angular.forEach(data, function (value, key) {
formData.append(key, value);
});
return formData;
}
})
.then(function onSuccess(response) {
if (response.data = "Ok") {
$window.location.reload();
}
})
.catch(function onError(response) {
console.info("Error")
});
}
Модель на С#
[ScaffoldColumn(false)]
public int Id { get; set; }
[ScaffoldColumn(false)]
public string User { get; set; }
[Required(ErrorMessage = "")]
[StringLength(100, MinimumLength = 1, ErrorMessage = "")]
public string Headline { get; set; }
[Required(ErrorMessage = "")]
[StringLength(1000, MinimumLength = 1, ErrorMessage = "")]
public string BodyText { get; set; }
[ScaffoldColumn(false)]
public DateTime? Date_Time { get; set; }
public IFormFile ImgPost { get; set; }
И подпись метода
[HttpPost]
[Route("create-post")]
public async Task<object> PostSaveOnFile(PostViewModel model)
{
Как мне изменить модель в # public IFormFile ImgPost { get; набор; } И внесите изменения в мой контроллер angularJS, и я смогу отправить массив файлов. Спасибо.
Как я понял проблема в моей директиве fileReader
(function (angular) {
angular.module('app').directive('fileModel', ['$parse', function ($parse) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
var model = $parse(attrs.fileModel);
var modelSetter = model.assign;
element.bind('change', function() {
scope.$apply(function() {
modelSetter(scope, element[0].files[0]);
});
});
}
};
}]);
})(window.angular);
Если я изменю свою модель С# на IList или IEnumerable, это будет только первый файл. Я не понимал, как изменить мою директиву на массив


I did nor understand how to change my derective to array
app.directive('fileModel', ['$parse', function ($parse) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
var model = $parse(attrs.fileModel);
var modelSetter = model.assign;
element.bind('change', function() {
scope.$apply(function() {
̶m̶o̶d̶e̶l̶S̶e̶t̶t̶e̶r̶(̶s̶c̶o̶p̶e̶,̶ ̶e̶l̶e̶m̶e̶n̶t̶[̶0̶]̶.̶f̶i̶l̶e̶s̶[̶0̶]̶)̶;̶
modelSetter(scope, element[0].files);
});
});
}
};
}]);
Измените вызов modelSetter, чтобы он возвращал массив.
Сначала вам нужно обновить директиву fileModel, чтобы установить массив файлов вместо одного файла. Вы можете использовать этот ответ, но результирующий массив будет иметь тип FileList, и я предлагаю вам преобразовать его в Array, потому что он будет более гибким в сочетании с другими изменениями в коде.
app.directive('fileModel', ['$parse', function ($parse) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
var model = $parse(attrs.fileModel);
var modelSetter = model.assign;
element.bind('change', function() {
scope.$apply(function() {
modelSetter(scope, Array.from(element[0].files));
});
});
}
};
}]);
Чтобы позволить ASP.NET Core правильно связать Array (или List), вам нужно добавить все значения массива с одним и тем же ключом в FormData. Например, если у вас есть
public List<string> Strings { get; set; }
вам нужно будет добавить значения с помощью клавиши Strings
formData.append("Strings", "value1");
formData.append("Strings", "value2");
formData.append("Strings", "value3");
Поэтому вам нужно обновить функцию transformRequest, чтобы правильно добавить массив файлов в FormData.
function (data, headersGetter) {
var formData = new FormData();
angular.forEach(data, function (value, key) {
//you could check if value is FileList
//but your model can hold array of primitive values like ["val1", "val2", "val3"]
//this single check for Array covers all cases
//and you don't need to have different check for FileList
if (value instanceof Array) {
for (var i = 0; i < value.length; i++) {
formData.append(key, value[i]);
}
return;
}
formData.append(key, value);
});
return formData;
}
Не помогло. Теперь в моей модели ImgPost null в контроллере API :(