我一直在努力在我的 razor 页面上实现 dropzone.js。我目前正在尝试创建一个帮助台,其中 dropzone 允许用户拖动文件以连同其票证一起上传。我没有太多运气将文件上传到剃刀页面的后端。我可以让它与常规 标签一起使用,但不能与 dropzone 一起使用。 HttpContext.Request.Form.Files 属性为空,如果我绑定 IformFile 列表,或者至少尝试绑定,我也不会获取该文件。
我很幸运地将文件显示在单独控制器中的 Form.Files 中,但我不确定如何将文件位置从控制器传递到在后端处理的帮助票证。我知道我可以在后端处理整个表单上传,但我将对所有表单的文件上传进行更改,如果我必须有一个控制器,它应该能够仅处理文件上传部分和然后返回razor后端完成剩余的表单提交 文件上传保存在我的 wwwroot 文件夹中名为“附件”的文件夹中,然后我有一个票证上传模型,用于存储它们的位置以及与之关联的票证(每个票证可以有多个上传),所以我必须有某种方式来处理在其模型中创建帮助票证,然后创建文件上传及其位置。
这是我的代码的相关部分:
首先是我的拖放区配置:
$(document).ready(function () {
Dropzone.autoDiscover = false;
console.log(window.location.pathname); // path returned here is what is put in url. Will use for other razor pages implementing this in the future?
$("#fileUploadArea").dropzone({
url: "/api/fileupload", // or to razor backend: /IT/Help (matches location.pathname)
autoProcessQueue: false,
addRemoveLinks: true,
acceptedFiles: ".png,.jpg,.gif,.jpeg,.bmp",
uploadMultiple: true,
maxFiles: 10,
headers: { "RequestVerificationToken": $('input[name="__RequestVerificationToken"]').val() },
paramName: "files",
init: function () {
var myDropzone = this;
myDropzone.options.addRemoveLinks = true;
myDropzone.options.dictRemoveFile = "Remove";
//myDropzone.paramName = () => "files";
this.on("success", function (file, response) {
alert("success");
});
this.on("error", function (file, errorMsg) {
alert("error");
console.error(errorMsg);
});
//Manually submit form with files?
$('#wmf-help-submit-button').on('click', function (e) {
myDropzone.processQueue();
});
}
});
});
形式:
<form method="POST" enctype="multipart/form-data" class="" id="ticketForm" asp-action="/Index">
@* @Html.AntiForgeryToken(); *@
<head>
<title></title>
</head>
<body>
<!-- Two inputs, one for a title and another for a body/description omitted -->
<!-- Image Uploads -->
<div class="col-12 text-dark">
<p>Please upload any screenshots below:</p>
<div id="fileUploadArea" class="dropzone text-center">
<!-- <input type="file" name="Uploads" accept=".jpg, .jpeg, .png" multiple hidden> -->
<span class="dz-message">Drop files here or <span class="text-decoration-underline">Click to browse</span></span>
</div>
<!-- TODO: implement fallback for no js? Non-DZ way that works. -->
<!-- <label for="image_uploads">Choose images to upload (PNG, JPG)</label>
<div id="wmf-files-to-upload">
<input type="file" name="Uploads" accept=".jpg, .jpeg, .png" multiple>
</div> -->
</div>
<div class="col-12 text-center mt-4 mb-2">
<input id="wmf-help-submit-button" class="wmf-button-main btn form-control text-center" type="submit" />
</div>
</form>
我有一个剃刀后端,如下所示:
namespace mynamespacehere
{
[Authorize]
public class IndexModel : PageModel
{
private readonly IUnitofWork _unitofWork;
private readonly IWebHostEnvironment _webHostEnvironment;
/* Irrelevant fields removed */
public HelpDeskTicket HelpTicket { get; set; }
[BindProperty]
public List<IFormFile> Uploads { get; set; } // DZ uploads don't show here either.
/* ... Get method omitted */
public async Task<IActionResult> OnPost()
{
/* ... handling other form fields validation */
/* ... Created help ticket in DB (Help ticket does not have upload as part of it's model, upload references ticket instead) */
/* file upload area. files put in via dropzone are not showing here. */
// Upload Files if there are any. Could be in a controller instead?
// YOU MUST ALWAYS UPLOAD FILES AFTER COMMITTING INITIAL TICKET TO DB OTHERWISE THERE WILL NOT BE A
// TICKETID TO ASSOCIATE WITH THE UPLOADS!
#region File Upload
var files = HttpContext.Request.Form.Files;
if (files.Count > 0)
{
string webRootPath = _webHostEnvironment.WebRootPath;
foreach (var file in files)
{
HelpDeskTicketUpload ticketUpload = new HelpDeskTicketUpload();
string fileName = Guid.NewGuid().ToString();
var uploadpath = Path.Combine(webRootPath, @"attachments\helpdesk\");
var extension = Path.GetExtension(file.FileName);
var filePath = uploadpath + fileName + extension;
using var fileStream = System.IO.File.Create(filePath);
file.CopyTo(fileStream);
ticketUpload.HelpDeskTicketId = HelpTicket.Id;
ticketUpload.Filetype = extension;
ticketUpload.Location = @"\attachments\helpdesk\" + fileName + extension;
_unitofWork.HelpDeskTicketUpload.Add(ticketUpload);
}
}
#endregion
TempData["success"] = "Your help desk message was sent successfully!";
return RedirectToPage("./Index");
}
}
}
可以获取文件的控制器,但我不知道如何传递给razor进行表单处理:
namespace mynamespacehere
{
[Route("api/[controller]")]
[ApiController]
public class FileuploadController : Controller
{
private readonly UnitofWork _unitOfWork;
private readonly IWebHostEnvironment _webHostEnvironment;
public FileuploadController(UnitofWork unitofWork, IWebHostEnvironment webHostEnvironment)
{
_unitOfWork = unitofWork;
_webHostEnvironment = webHostEnvironment;
}
[HttpPost]
public async Task<IActionResult> SaveFile()
{
var files = HttpContext.Request.Form.Files;
//var filesReq = HttpContext.Request.Form.Files;
if (files.Count > 0)
{
string webRootPath = _webHostEnvironment.WebRootPath;
foreach (var file in files)
{
HelpDeskTicketUpload ticketUpload = new HelpDeskTicketUpload();
string fileName = Guid.NewGuid().ToString();
var uploadpath = Path.Combine(webRootPath, @"attachments\helpdesk\");
var extension = Path.GetExtension(file.FileName);
var filePath = uploadpath + fileName + extension;
using var fileStream = System.IO.File.Create(filePath);
file.CopyTo(fileStream); //Not showing up in filepath need to debug this but can be considered a separate issue.
}
}
return Ok("upload successful"); //Don't know how to return response/file locations to post backend.
}
}
}
回顾一下,我有两种我真正想问的方法。首先是将来自 Dropzone 的文件上传到剃刀后端,第二个是,如果我必须使用控制器,我将如何将文件位置(可能上传了多个文件)传回剃刀,然后索引到数据库。
下面是razor页面的工作演示,大家可以参考一下。
<form method="POST" enctype="multipart/form-data" class="" id="ticketForm">
<div id="fileUploadArea" class="my-dropzone">
<span class="dz-message" >Drop files here or <span class="text-decoration-underline" >Click to browse</span></span>
</div>
<div class="col-12 text-center mt-4 mb-2">
<input id="wmf-help-submit-button" class="wmf-button-main btn form-control text-center" type="submit" />
</div>
</form>
<script src="https://code.jquery.com/jquery-3.7.0.js"></script>
<script src="https://unpkg.com/dropzone@5/dist/min/dropzone.min.js"></script>
<link rel="stylesheet"
href="https://unpkg.com/dropzone@5/dist/min/dropzone.min.css"
type="text/css" />
<script>
// Dropzone has been added as a global variable.
const dropzone = new Dropzone("div.my-dropzone", {
url: "/Index",
autoProcessQueue: false,
addRemoveLinks: true,
acceptedFiles: ".png,.jpg,.gif,.jpeg,.bmp",
uploadMultiple: true,
maxFiles: 10,
parallelUploads: 100,
maxFiles: 100,
headers: { "RequestVerificationToken": $('input[name="__RequestVerificationToken"]').val() },
paramName: "files",
init: function () {
var myDropzone = this;
myDropzone.options.addRemoveLinks = true;
myDropzone.options.dictRemoveFile = "Remove";
//myDropzone.paramName = () => "files";
this.on("success", function (file, response) {
alert("success");
});
this.on("error", function (file, errorMsg) {
alert("error");
console.error(errorMsg);
});
//Manually submit form with files?
$('#wmf-help-submit-button').on('click', function (e) {
e.preventDefault();
myDropzone.processQueue();
});
}
});
</script>
剃刀后端结果: