我希望网站的用户同时上传多张图片,最多可以上传5张图片。我创建了所有ViewModels
以及[HttpPost]
方法来处理列表图像并迭代每个图像,保存它们。
我的问题是:如何在Post方法中收到该列表?
我的ViewModel有以下代码:
public class ImageCreateViewModel
{
public int ImageId { get; set; }
public int CollectionId { get; set; }
[Required(ErrorMessage = "Please enter a description of the photo.")]
[MaxLength(50)]
public string Description { get; set; }
[Required(ErrorMessage = "Please attach an image.")]
public HttpPostedFileBase Image { get; set; }
public string Location { get; set; }
public int Order { get; set; }
}
public class ImagesCreateViewModel : ImageCreateViewModel
{
public List<ImageCreateViewModel> Images { get; set; }
public MyEnumerator GetEnumerator()
{
return new MyEnumerator(this);
}
}
public class MyEnumerator
{
int index;
ImagesCreateViewModel imagesCreateViewModel;
public MyEnumerator(ImagesCreateViewModel imagesCreateViewModel)
{
this.imagesCreateViewModel = imagesCreateViewModel;
index = -1;
}
public bool MoveNext()
{
index++;
return (index < imagesCreateViewModel.Images.Count());
}
public ImageCreateViewModel Current
{
get
{
return (imagesCreateViewModel.Images[index]);
}
}
}
这是我的控制器:
[HttpPost]
public ActionResult CreateImages(ImagesCreateViewModel imagesEditViewModel)
{
if (!ModelState.IsValid)
{
return View(imagesEditViewModel);
}
foreach (ImageCreateViewModel imageCreateViewModel in imagesEditViewModel)
{
string fileName = Guid.NewGuid().ToString();
string serverPath = Server.MapPath("~");
string contentPath = String.Format("Content\\{0}\\Content\\Images\\{1}", Helper.Helper.ResolveBrand(), fileName);
string imagePath = serverPath + contentPath;
bool success = Helper.Helper.SaveImage(imagePath, imageCreateViewModel.Image.InputStream);
if (success)
{
Image image = new Image
{
Collection = ds.Single<Collection>(c => c.CollectionId == imageCreateViewModel.CollectionId),
Description = imageCreateViewModel.Description,
Location = contentPath,
Order = Helper.Helper.GetImageOrder(imageCreateViewModel.CollectionId)
};
ds.InsertOnSubmit<Image>(image);
ds.SubmitChanges();
}
else
//TODO: Write Error to them
success = false;
}
return RedirectToAction("Collection");
}
但是当我为这个方法生成一个View时,它只能一次操作一个图像(我必须编辑它以允许它们上传图像):
@using (Html.BeginForm(null, null, FormMethod.Post, new { enctype = "multipart/form-data" }))
{
@Html.ValidationSummary(true)
<fieldset>
<legend>New Image</legend>
<div class="editor-label">
@Html.LabelFor(model => model.Description)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Description)
@Html.ValidationMessageFor(model => model.Description)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.Image)
</div>
<div class="editor-field">
@Html.ValidationMessageFor(model => model.Image)
<input type="file" name="Image" />
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
答案 0 :(得分:3)
以下是我在网站上用来上传多张图片的一些代码:
好的,所以这是一个如何做的简单示例。最终结果:
HTML标记是一个简单的表单,带有提交按钮。
@using (Html.BeginForm("Create", "Product", FormMethod.Post, new { enctype = "multipart/form-data" })) {
@Html.ValidationSummary()
<div class="form-field">
<p>Select pictures:</p>
<div class="upload-container">
<div class="upload">
<input type="file" name="files" id="file1" />
<img src="@Url.Content("~/Public/images/delete.png")" alt="Remove picture." />
</div>
</div>
</div>
<div class="form-field">
<input type="submit" value="Create" />
</div>
}
我们还需要一些jQuery魔术,这样每次有人添加图像时,我们都会让它们根据需要添加更多。用户可以上传N个图像。我们使用on()
方法,以便事件绑定在每个新创建的元素上。
请注意,添加的输入的名称是“files”,我们在ActionMethod中使用的名称相同。
<script type="text/javascript">
$(document).ready(function () {
var currentImage = 1;
$("body").on("change", "input[name='files']", function () {
var pathToRemoveIcon = "@Url.Content("~/Public/images/delete.png")";
currentImage = currentImage + 1;
var htmlToAppend = '<div class="upload"><input type="file" name="files" id="file' + currentImage + '" /><img src="' + pathToRemoveIcon + '" alt="Remove picture." /></div>';
$('.upload-container').append(htmlToAppend);
}).on("click", ".upload img", function () {
if ($(this).parent().siblings().length > 0) {
$(this).parent().remove();
}
});
});
</script>
最后控制器代码我们收到了我们想要绑定的模型,以及可枚举的文件:
[HttpPost]
public ActionResult Create(ProductModel model, IEnumerable<HttpPostedFileBase> files)
{
try
{
if (ModelState.IsValid)
{
foreach (var file in files)
{
// Verify that the user selected a file
if (file != null && file.ContentLength > 0)
{
// extract only the filename
var fileName = Path.GetFileName(file.FileName);
// etc.
}
}
}
return RedirectToAction("Index");
}
catch
{
return View(model);
}
}
答案 1 :(得分:2)
这是有可能的,但你要做的不仅仅是自动搭建视图。以下是Phil Haack的博客文章,详细介绍了如何构建对MVC和集合中的ModelBinding友好的HTML视图。
http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx
Scott Hansleman关于这个主题的另一篇文章。 http://www.hanselman.com/blog/ASPNETWireFormatForModelBindingToArraysListsCollectionsDictionaries.aspx
答案 2 :(得分:1)
我不确定这是否会转移到正确生成模型,但如果您能够使用HTML5,那么您可以使用input multiple
属性来允许多个输入。虽然
And, here is a decent example that makes things a little prettier
答案 3 :(得分:0)
MVC允许您通过接受HttpPostedFileBase
对象列表来接受操作中的多个文件上传。您需要确保所有文件上传控件的名称与操作方法的参数相同。
public ActionResult UploadFiles(IEnumerable<HttpPostedFileBase> files)
{
}
答案 4 :(得分:-1)
您可以使用一个帖子上传多个文件。
只需为每个文件名称设置一个不同的文件名称,并在控制器中执行Request.Files
中的foreach。类似的东西:
foreach (var file in Request.Files)
{
if (file.ContentLength > 0)
... do something ...
}