javascript - 使用 Dropzone 和 Laravel 上传产品
问题描述
我想使用 Dropzone 上传带有多个图像的产品,我有一个包含价格、名称等其他字段的表单。我看过其他教程,但他们只上传图像而不是一次带有其他字段(价格、名称)的图像。我已经设置了显示预览的 Dropzone,但是如果我提交按钮,我会得到验证Please enter product image
。如何使用 Dropzone 将图像传递给控制器?
控制器
public function store(Request $request)
{
$formInput=$request->except('filename');
$product = product::create(array_merge($formInput, [
'user_id' => Auth::user()->id
]));
foreach ($request->file as $photo) {
$filename = $photo->store('public/photos');
ProductsPhoto::create([
'product_id' => $product->id,
'filename' => $filename
]);
}
}
刀
//The form
<div class="panel-body">
<form>
@csrf
<input type="hidden" value="{{csrf_token()}}" id="token"/>
<label for="pro_name">Name</label>
<input type="text" class="form-control" name="pro_name" id="pro_name" placeholder="Enter product name">
<label for="pro_price">Price</label>
<input type="text" class="form-control" name="pro_price" id="pro_price" placeholder="Enter price">
<label for="photos">Choose 5 Images</label>
<div class="needsclick dropzone" id="document-dropzone"> // Display images preview
</div>
<input type="submit" class="btn btn-primary" value="Submit" id="btn"/>
</div>
阿贾克斯
//This is how I submit the form
<script>
var token = $("#token").val();
$(document).ready(function(){
$("#btn").click(function (e) {
e.preventDefault();
$("#loading").show();
var url = '{{ route('product.store') }}';
var form = $('form')[0]; // You need to use standard javascript object here
var formData = new FormData(form);
formData.append('_token', token); // adding token
$.ajax({
url: url,
data: formData, //just that without variables
type: 'POST',
cache: false,
contentType: false, // NEEDED, DON'T OMIT THIS (requires jQuery 1.6+)
processData: false, // NEEDED, DON'T OMIT THIS
success:function(data){
if($.isEmptyObject(data.error)){
$("#msg").html("Product has been added successfull");
$("#msg").fadeOut(3000);
window.location.href = "<?php echo url('seller/product') ?>";
$("#loading").hide();
}
else{
printErrorMsg(data.error);
}
}
});
function printErrorMsg (msg) {
$("#loading").hide();
$(".print-error-msg").find("ul").html('');
$(".print-error-msg").css('display','block');
$.each( msg, function( key, value ) {
$(".print-error-msg").find("ul").append('<li>'+value+'</li>');
});
}
});
});
var uploadedDocumentMap = {}
Dropzone.options.documentDropzone = {
url: '{{ route('product.store') }}',
maxFilesize: 10, // MB
addRemoveLinks: true,
headers: {
'X-CSRF-TOKEN': "{{ csrf_token() }}"
},
success: function (file, response) {
$('form').append('<input type="hidden" name="document[]" value="' + file.name + '">')
uploadedDocumentMap[file.name] = response.name
},
removedfile: function (file) {
file.previewElement.remove()
var name = ''
if (typeof file.file_name !== 'undefined') {
name = file.file_name
} else {
name = uploadedDocumentMap[file.name]
}
$('form').find('input[name="document[]"][value="' + name + '"]').remove()
},
init: function () {
@if(isset($project) && $project->document)
var files =
{!! json_encode($project->document) !!}
for (var i in files) {
var file = files[i]
this.options.addedfile.call(this, file)
file.previewElement.classList.add('dz-complete')
$('form').append('<input type="hidden" name="document[]" value="' + file.file_name + '">')
}
@endif
}
}
</script>
解决方案
您的代码和您的概念中有些事情是不对的(至少在我看来):
- 您需要阻止默认行为,
#btn
因为您需要拦截表单提交。否则,表单只会作为GET
请求提交(默认行为是什么)。
$("#btn").click(function (e) {
e.preventDefault();
// ...
}
<form>
元素未关闭。此外,不要覆盖_ token
JavaScript 中的 ,而只是添加@csrf
到表单中。Larvel 和 jQuery 将为您处理一切。
<form>
@csrf
- 我想我明白你现在想要达到的目标。Dropzone 正在直接上传(= POST 请求)文件,因此您需要一个单独的路由(或另一个代码分支)来处理文件上传。然后,您可以获取先前上传的文件的文件名并将其作为
hidden
输入字段附加,如下所示:
success: function (file, response) {
$('form').append('<input type="hidden" name="document[]" value="' + file.name + '">')
},
您将在控制器的方法中收到pro_name
,和一个包含上传文件名称的pro_price
数组。document
按照您的逻辑,该文件必须已经存在于存储中,因为它是由 Dropzone 操作上传的。然后,您可以将其保存filename
到数据库或其他任何内容中,并将其用作以后访问文件的参考。无论如何,我不建议使用客户端提供的文件名进行存储,因为它可能不是唯一的。Laravel 为这种情况提供了很多有用的工具:https ://laravel.com/docs/5.7/filesystem#file-uploads
推荐阅读
- java - 从非自动实例化类中的属性设置静态变量
- authentication - PingIdentity:配置 SAML 连接:您的更改无法保存
- angular - single-spa-angular 当我们刷新浏览器时,微前端应用程序中的多个路由不起作用(GitHub 代码可用)
- python - `ModuleNotFoundError: No module named 'psutil'` 导入 psutil 模块时
- azure-application-insights - 从 NLog 发送时,Application Insights 数据是否会被采样?
- javascript - 在表单中渲染一个 button[type="submit"] 触发 onSubmit 回调
- mariadb - MariaDB 测量值 JSON_EXTRACT
- bash - 使 Deno 脚本全球可用
- pandas - 如何在单个 CSV 中表示标准化数据
- java - Java - 递归获取地图的所有键