Laravel 5 使用 AJAX 时文件上传不起作用
Laravel 5 file upload not working when using AJAX
我以前在处理 Laravel 时从未遇到过这个问题。
我有一个表格,可以插入产品详细信息,其中还有一个图像字段。
以下是我如何创建用于插入产品详细信息的视图:
{!! Form::open(['url' => '/admin/products', 'autocomplete' => 'off', 'id' => 'formAddProduct', 'files' => true]) !!}
<div class="errors"></div>
@include('admin.products.form', ['submitButtonText' => 'Add Product', 'submitButtonId' => 'btnAddProduct'])
{!! Form::close() !!}
form.blade.php:
<div class="form-group">
{!! Form::label('code', 'Code') !!}
{!! Form::text('code', null, ['class' => 'form-control']) !!}
</div>
<div class="form-group">
{!! Form::label('name', 'Name:') !!}
{!! Form::text('name', null, ['class' => 'form-control']) !!}
</div>
<div class="form-group">
{!! Form::label('category_id', 'Category:') !!}
{!! Form::select('category_id', $categories, null, ['class' => 'form-control']) !!}
</div>
<div class="form-group">
{!! Form::label('short_description', 'Short Description:') !!}
{!! Form::text('short_description', null, ['class' => 'form-control']) !!}
</div>
<div class="form-group">
{!! Form::label('description', 'Long Description:') !!}
{!! Form::text('description', null, ['class' => 'form-control']) !!}
</div>
<div class="form-group">
{!! Form::label('price', 'Price:') !!}
{!! Form::text('price', null, ['class' => 'form-control']) !!}
</div>
<div class="form-group">
{!! Form::label('discount_price', 'Discount Price:') !!}
{!! Form::text('discount_price', null, ['class' => 'form-control']) !!}
</div>
<div class="form-group">
{!! Form::label('display', 'Display Status:') !!}
{!! Form::select('display', ['Enabled' => 'Enabled', 'Disabled' => 'Disabled'], null, ['class' => 'form-control']) !!}
</div>
<div class="form-group">
{!! Form::label('image_file', 'Image:') !!}
{!! Form::file('image_file', ['id' => 'image_file', 'class' => 'form-control input-sm']) !!}
</div>
<div class="form-group">
{!! Form::submit($submitButtonText, ['class' => 'btn btn-primary btn-block', 'id' => $submitButtonId]) !!}
</div>
控制器方法:
public function store( Request $request ) {
$this->validate($request, [
'code' => 'required|alpha_dash|unique:products',
'name' => 'required',
'category_id' => 'required|integer',
'short_description' => 'string',
'description' => 'required',
'price' => 'required|regex:/^\d*(\.\d{2})?$/',
'discount_price' => 'regex:/^\d*(\.\d{2})?$/',
'display' => 'required|in:Enabled,Disabled',
'image_file' => 'mimes:jpg'
]);
if ( $request->ajax() ) {
Product::create( $request->all() );
if ( $request->file( 'image_file' ) ) {
$filename = Safeurl::make( $request->get( 'code' ) );
$image = Image::make( $request->file( 'image_file' ) );
$path = public_path( 'images/uploads/products/' );
$image->resize( 450, 450 )->save( $path.$filename.'.jpg', 100 );
} else {
return response(['msg' => 'No File']);
}
return response(['status' => 'success', 'msg' => 'The product has been added successfully.']);
}
return response(['status' => 'failed', 'msg' => 'The product could not be added successfully.']);
}
和 ajax:
$('#btnAddProduct').on('click', function() {
var inputData = $('#formAddProduct').serialize();
$.ajax({
url: '{{ url('/admin/products') }}',
type: 'POST',
data: inputData,
success: function( message ) {
alert( message.msg );
if ( message.status === 'success' ) {
toastr.success('Product added successfully.');
toastr.options.closeButton = true;
toastr.options.showMethod = "slideDown";
toastr.options.hideMethod = "slideUp";
$('input').val( '' );
$('select').val( '' );
}
},
error: function( data ) {
if ( data.status === 422 ) {
var errors = data.responseJSON;
var errorsHtml = '<div class="alert alert-danger"><ul>';
errorsHtml += '<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>';
$.each( errors, function( key, value ) {
errorsHtml += '<li>' + value[0] + '</li>'; //showing only the first error.
});
errorsHtml += '</ul></div>';
$( '.errors' ).html( errorsHtml );
}
}
});
return false;
});
我得到的错误是No file
当我执行 var_dump( $request->file( 'image_file' ) );
时,我在 chrome
的响应选项卡中得到 null
当我执行 var_dump( Input::file( 'image_file' ) );
时,我在 chrome
的响应选项卡中得到 null
我哪里弄错了?请帮助我。谢谢。
P.S.: 我已经使用 Intervention
作为我的图片上传功能。
serialize() 方法不发送文件信息供远程处理程序处理。另一种方法是使用 FormData。
请参阅此 link 示例:http://portfolio.planetjon.ca/2014/01/26/submit-file-input-via-ajax-jquery-easy-way/
注意:在 jQuery ajax 请求中将 processData 和 contentType 设置为 false 很重要,否则在 jQuery 尝试处理它时会导致错误。
您应该在 ajax 调用
中添加 data: formData,
和 async: false,
所以你的 ajax 将是
$("form[name='yourformname']").submit(function(e) {//If you use form submit then have your form name here
//$('#btnAddProduct').on('click', function() {
var inputData = new FormData($(this)[0]);
//var inputData = $('#formAddProduct').serialize(); not matter :p
e.preventDefault();
$.ajax({
url: '{{ url('/admin/products') }}',
type: 'POST',
data: inputData,
async: false,
success: function( message ) {
alert( message.msg );
if ( message.status === 'success' ) {
toastr.success('Product added successfully.');
toastr.options.closeButton = true;
toastr.options.showMethod = "slideDown";
toastr.options.hideMethod = "slideUp";
$('input').val( '' );
$('select').val( '' );
}
},
error: function( data ) {
if ( data.status === 422 ) {
var errors = data.responseJSON;
var errorsHtml = '<div class="alert alert-danger"><ul>';
errorsHtml += '<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>';
$.each( errors, function( key, value ) {
errorsHtml += '<li>' + value[0] + '</li>'; //showing only the first error.
});
errorsHtml += '</ul></div>';
$( '.errors' ).html( errorsHtml );
}
}
});
return false;
});
更新:
在 ajax 通话中转 async:true
在你的 Laravel 验证器规则中加入这个 image_file' => 'mimes:jpeg,jpg,JPG'
在发出包含包装在 formData 对象中的文件的 Ajax 请求之前,您需要了解一些陷阱和技巧。
- 确保设置
contentType: false
和 processData: false
- 如果您只是在 formData 上附加文件,请确保您像这样访问文件数据
//This function collects all form fields to be appended
//to a formData object
function collectFormData($form){
var formdata = new FormData(), value, fieldId,$field ;
var formFields = ['title','summary','categories','tags','screenshot','flowchart'];
$form.find('input , select , textarea').each(function(){
$field = $(this);
fieldId = $field .attr('id')
//check whether this field is needed
if($.inArray(fieldId, formFields) !== -1 ){
switch (fieldId) {
//access the file content of the file input
case 'screenshot':
value = $field[0].files[0];
break;
case 'flowchart':
value = $field[0].files[0];
break;
default:
value = $field.val();
break;
}//end switch
formdata.append(fieldId, value)
}//end if
});
return formdata;
}
function submitFormData(){
$('.submit-btn').on('click', function(e){
e.preventDefault();
var $thisBtn = $(this);
var $form = $thisBtn.closest('form');
var formdata = collectFormData($form);
//add token for laravel projects
$.ajaxSetup({'headers': {'X-CSRF-TOKEN':$form.find('input[name="_token"]').val()}});
//prepare an ajax request to send form details
$.ajax({
url: $form.attr('action'),
method: "post",
processData: false, //Do not allow proccessing of the data
dataType: "json", //you can change this property
data: formdata, //this is our formData object being passed here
async: false,
cache: false,
contentType: false, //very important for sending files
success: function(data) {
console.log(data)
}, error:function(data){
console.log(data)
}
});//end ajax request
return false;
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form action="path/to/your/backendscript" id="uploadForm" method="post">
<input type="text" name="title" id="title" >
<textarea name="summary" id="summary" cols="30" rows="10"></textarea>
<select name="categories[]" multiple id="categories">
<option>Web Development</option>
<option>Java Programming</option>
<option>PHP programming</option>
</select>
<select name="tags[]" multiple id="tags">
<option>AJAX</option>
<option >Swing Components</option>
<option>Laravel</option>
</select>
<input type="file" name="screenshot" id="screenshot">
<input type="file" name="flowchart" id="flowchart">
<button class="submit-btn" type="submit">Submit</button>
</form>
这是非常适合我的解决方案。干杯!
我以前在处理 Laravel 时从未遇到过这个问题。
我有一个表格,可以插入产品详细信息,其中还有一个图像字段。
以下是我如何创建用于插入产品详细信息的视图:
{!! Form::open(['url' => '/admin/products', 'autocomplete' => 'off', 'id' => 'formAddProduct', 'files' => true]) !!}
<div class="errors"></div>
@include('admin.products.form', ['submitButtonText' => 'Add Product', 'submitButtonId' => 'btnAddProduct'])
{!! Form::close() !!}
form.blade.php:
<div class="form-group">
{!! Form::label('code', 'Code') !!}
{!! Form::text('code', null, ['class' => 'form-control']) !!}
</div>
<div class="form-group">
{!! Form::label('name', 'Name:') !!}
{!! Form::text('name', null, ['class' => 'form-control']) !!}
</div>
<div class="form-group">
{!! Form::label('category_id', 'Category:') !!}
{!! Form::select('category_id', $categories, null, ['class' => 'form-control']) !!}
</div>
<div class="form-group">
{!! Form::label('short_description', 'Short Description:') !!}
{!! Form::text('short_description', null, ['class' => 'form-control']) !!}
</div>
<div class="form-group">
{!! Form::label('description', 'Long Description:') !!}
{!! Form::text('description', null, ['class' => 'form-control']) !!}
</div>
<div class="form-group">
{!! Form::label('price', 'Price:') !!}
{!! Form::text('price', null, ['class' => 'form-control']) !!}
</div>
<div class="form-group">
{!! Form::label('discount_price', 'Discount Price:') !!}
{!! Form::text('discount_price', null, ['class' => 'form-control']) !!}
</div>
<div class="form-group">
{!! Form::label('display', 'Display Status:') !!}
{!! Form::select('display', ['Enabled' => 'Enabled', 'Disabled' => 'Disabled'], null, ['class' => 'form-control']) !!}
</div>
<div class="form-group">
{!! Form::label('image_file', 'Image:') !!}
{!! Form::file('image_file', ['id' => 'image_file', 'class' => 'form-control input-sm']) !!}
</div>
<div class="form-group">
{!! Form::submit($submitButtonText, ['class' => 'btn btn-primary btn-block', 'id' => $submitButtonId]) !!}
</div>
控制器方法:
public function store( Request $request ) {
$this->validate($request, [
'code' => 'required|alpha_dash|unique:products',
'name' => 'required',
'category_id' => 'required|integer',
'short_description' => 'string',
'description' => 'required',
'price' => 'required|regex:/^\d*(\.\d{2})?$/',
'discount_price' => 'regex:/^\d*(\.\d{2})?$/',
'display' => 'required|in:Enabled,Disabled',
'image_file' => 'mimes:jpg'
]);
if ( $request->ajax() ) {
Product::create( $request->all() );
if ( $request->file( 'image_file' ) ) {
$filename = Safeurl::make( $request->get( 'code' ) );
$image = Image::make( $request->file( 'image_file' ) );
$path = public_path( 'images/uploads/products/' );
$image->resize( 450, 450 )->save( $path.$filename.'.jpg', 100 );
} else {
return response(['msg' => 'No File']);
}
return response(['status' => 'success', 'msg' => 'The product has been added successfully.']);
}
return response(['status' => 'failed', 'msg' => 'The product could not be added successfully.']);
}
和 ajax:
$('#btnAddProduct').on('click', function() {
var inputData = $('#formAddProduct').serialize();
$.ajax({
url: '{{ url('/admin/products') }}',
type: 'POST',
data: inputData,
success: function( message ) {
alert( message.msg );
if ( message.status === 'success' ) {
toastr.success('Product added successfully.');
toastr.options.closeButton = true;
toastr.options.showMethod = "slideDown";
toastr.options.hideMethod = "slideUp";
$('input').val( '' );
$('select').val( '' );
}
},
error: function( data ) {
if ( data.status === 422 ) {
var errors = data.responseJSON;
var errorsHtml = '<div class="alert alert-danger"><ul>';
errorsHtml += '<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>';
$.each( errors, function( key, value ) {
errorsHtml += '<li>' + value[0] + '</li>'; //showing only the first error.
});
errorsHtml += '</ul></div>';
$( '.errors' ).html( errorsHtml );
}
}
});
return false;
});
我得到的错误是No file
当我执行 var_dump( $request->file( 'image_file' ) );
时,我在 chrome
null
当我执行 var_dump( Input::file( 'image_file' ) );
时,我在 chrome
null
我哪里弄错了?请帮助我。谢谢。
P.S.: 我已经使用 Intervention
作为我的图片上传功能。
serialize() 方法不发送文件信息供远程处理程序处理。另一种方法是使用 FormData。 请参阅此 link 示例:http://portfolio.planetjon.ca/2014/01/26/submit-file-input-via-ajax-jquery-easy-way/
注意:在 jQuery ajax 请求中将 processData 和 contentType 设置为 false 很重要,否则在 jQuery 尝试处理它时会导致错误。
您应该在 ajax 调用
中添加data: formData,
和 async: false,
所以你的 ajax 将是
$("form[name='yourformname']").submit(function(e) {//If you use form submit then have your form name here
//$('#btnAddProduct').on('click', function() {
var inputData = new FormData($(this)[0]);
//var inputData = $('#formAddProduct').serialize(); not matter :p
e.preventDefault();
$.ajax({
url: '{{ url('/admin/products') }}',
type: 'POST',
data: inputData,
async: false,
success: function( message ) {
alert( message.msg );
if ( message.status === 'success' ) {
toastr.success('Product added successfully.');
toastr.options.closeButton = true;
toastr.options.showMethod = "slideDown";
toastr.options.hideMethod = "slideUp";
$('input').val( '' );
$('select').val( '' );
}
},
error: function( data ) {
if ( data.status === 422 ) {
var errors = data.responseJSON;
var errorsHtml = '<div class="alert alert-danger"><ul>';
errorsHtml += '<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>';
$.each( errors, function( key, value ) {
errorsHtml += '<li>' + value[0] + '</li>'; //showing only the first error.
});
errorsHtml += '</ul></div>';
$( '.errors' ).html( errorsHtml );
}
}
});
return false;
});
更新:
在 ajax 通话中转
async:true
在你的 Laravel 验证器规则中加入这个
image_file' => 'mimes:jpeg,jpg,JPG'
在发出包含包装在 formData 对象中的文件的 Ajax 请求之前,您需要了解一些陷阱和技巧。
- 确保设置
contentType: false
和processData: false
- 如果您只是在 formData 上附加文件,请确保您像这样访问文件数据
//This function collects all form fields to be appended
//to a formData object
function collectFormData($form){
var formdata = new FormData(), value, fieldId,$field ;
var formFields = ['title','summary','categories','tags','screenshot','flowchart'];
$form.find('input , select , textarea').each(function(){
$field = $(this);
fieldId = $field .attr('id')
//check whether this field is needed
if($.inArray(fieldId, formFields) !== -1 ){
switch (fieldId) {
//access the file content of the file input
case 'screenshot':
value = $field[0].files[0];
break;
case 'flowchart':
value = $field[0].files[0];
break;
default:
value = $field.val();
break;
}//end switch
formdata.append(fieldId, value)
}//end if
});
return formdata;
}
function submitFormData(){
$('.submit-btn').on('click', function(e){
e.preventDefault();
var $thisBtn = $(this);
var $form = $thisBtn.closest('form');
var formdata = collectFormData($form);
//add token for laravel projects
$.ajaxSetup({'headers': {'X-CSRF-TOKEN':$form.find('input[name="_token"]').val()}});
//prepare an ajax request to send form details
$.ajax({
url: $form.attr('action'),
method: "post",
processData: false, //Do not allow proccessing of the data
dataType: "json", //you can change this property
data: formdata, //this is our formData object being passed here
async: false,
cache: false,
contentType: false, //very important for sending files
success: function(data) {
console.log(data)
}, error:function(data){
console.log(data)
}
});//end ajax request
return false;
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form action="path/to/your/backendscript" id="uploadForm" method="post">
<input type="text" name="title" id="title" >
<textarea name="summary" id="summary" cols="30" rows="10"></textarea>
<select name="categories[]" multiple id="categories">
<option>Web Development</option>
<option>Java Programming</option>
<option>PHP programming</option>
</select>
<select name="tags[]" multiple id="tags">
<option>AJAX</option>
<option >Swing Components</option>
<option>Laravel</option>
</select>
<input type="file" name="screenshot" id="screenshot">
<input type="file" name="flowchart" id="flowchart">
<button class="submit-btn" type="submit">Submit</button>
</form>
这是非常适合我的解决方案。干杯!