使用 Dropzone 和 Laravel 上传产品
Posted
技术标签:
【中文标题】使用 Dropzone 和 Laravel 上传产品【英文标题】:Product upload with Dropzone and Laravel 【发布时间】:2020-03-28 23:43:01 【问题描述】:我想使用 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>
【问题讨论】:
你为什么要设置contentType: false
?
提交表单时是否会导致问题?@Johannes
在这里你可以找到一个最小的工作示例:***.com/questions/41981922/… 我还注意到你在刀片模板中缺少@csrf 注释,否则 Laravel 将拒绝你的请求(参见laravel.com/docs/5.7/csrf ) 更改后,将console.log(data)
添加到success
回调。
是的,但据我所知,您还需要一个 name
属性。 @csrf
隐含地这样做了。
Here is an answer describing how to upload your form fields with a Dropzone image,当您单击一个按钮时。正如 Johannes 指出的那样,您的 CSRF 代码无效,只需使用 @csrf
。至于后端,Please enter product image
不在您向我们展示的代码中的任何位置,因此我们只能猜测那里可能存在问题。
【参考方案1】:
在你的代码和你的概念中有些事情是不对的(至少在我看来):
-
您需要阻止
#btn
的默认行为,因为您需要拦截表单提交。否则,表单只会作为GET
请求提交(默认行为是什么)。
$("#btn").click(function (e)
e.preventDefault();
// ...
<form>
元素未关闭。此外,不要在 JavaScript 中覆盖 _ token
,而只需将 @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
【讨论】:
以上是关于使用 Dropzone 和 Laravel 上传产品的主要内容,如果未能解决你的问题,请参考以下文章
如何克服 Laravel dropzone 文件上传中的 getClientOriginalName() 错误?