我正在尝试通过Ajax请求上传图像,似乎遇到了与此问题类似的问题,但它没有答案.我不确定它们是否完全一样,所以我会在这里发布所有细节,希望更多细节可以帮助别人找到答案.
我从我的代码中解释了下面的内容(删除了我认为与此问题无关的很多内容)所以你看到的任何错别字都可能只是我改变下面的代码.
以下内容包含在我的模型中:
use yii\web\UploadedFile;
...
class Image extends \yii\db\ActiveRecord
{
public $imageFile;
public function rules()
{
return [
[['imageFile'], 'file', 'skipOnEmpty' => true, 'extensions' => 'png, jpg'],
];
}
public function upload()
{
if ($this->validate()) {
$this->imageFile->saveAs('uploads/' . $this->imageFile->baseName . '.' . $this->imageFile->extension);
return true;
} else {
return false;
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的视图文件的一部分:
<?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]) ?>
<?= $form->field($model, 'title') ?>
<?= $form->field($model, 'imageFile')->fileInput() ?>
<?= Html::submitButton('Upload', ['class' => 'btn btn-success']) ?>
<?php ActiveForm::end(); ?>
Run Code Online (Sandbox Code Playgroud)
和视图中的Ajax
$('form').on('beforeSubmit', function(e) {
var form = $(this);
$.post(form.attr('action'), form.serialize()).done(function(result) {
console.log(result)
});
return false; // Prevent default form submit action
});
Run Code Online (Sandbox Code Playgroud)
以下是我的控制器
use yii\web\UploadedFile;
...
public function actionUpload()
{
$model = new Image();
if (Yii::$app->request->isAjax) {
$model->load(Yii::$app->request->post());
$model->imageFile = UploadedFile::getInstance($model, 'imageFile');
if ($model->upload()) {
$model->save(); // To save the title to the database
Yii::$app->getSession()->addFlash('success', 'Image uploaded');
return $this->redirect(['index']);
}
}
Yii::$app->response->format = Response::FORMAT_JSON;
return ['return' => 'just me testing here'];
}
Run Code Online (Sandbox Code Playgroud)
上面的Ajax只会将标题保存到数据库中,不会上传文件.如果我将所有内容转换为标准发布请求,我可以将其全部工作(标题保存到数据库,图像上传到正确的目录).如果我调试各种视图,模型和控制器,看起来我只是没有通过Ajax请求获取imageFile.该$model->load(Yii::$app->request->post());负载这是通过Ajax提交,那么为什么不是也拉文件标题?我想也许这$model->imageFiles = UploadedFile::getInstances($model, 'imageFiles');将是拉动Ajax提交文件的部分,但它似乎没有得到我需要的东西.作为测试,我甚至尝试将imageFile属性视为纯文本并将其分配给另一个要写入的数据库属性,并且它工作得很好.因此它似乎正在被正确地包含在模型中,而不是与Ajax提交一起发送.
任何人都可以告诉我,在Yii2中,我可以通过Ajax提交表单,包括所选文件?
问题
ajax中的问题是$_FILES细节不是在异步请求中发送的.当我们在没有ajax请求的情况下提交填充的表单并在PHP的后端进行调试时
echo '<pre>';
print_r($_FILES);
print_r($_POST);
echo '</pre>';
die;
Run Code Online (Sandbox Code Playgroud)
然后我们成功获得$_FILES和$_POST数据.
但是当我们在ajax请求中调试相同的东西时,我们只得到$_POST值,我们得到$_FILES了NULL.这导致我们得出结论,$_FILES我们的上述代码不会在ajax请求中发送数据.
解决方案
我们需要使用FormDataJavaScript.
它有什么作用?
简单地说,它增加了需要被上传到文件的所有必要的信息dataPARAM在$.ajaxOR填满$_FILES以及所有$_POST数据,即非文件输入如字符串号码等
在您的视图文件中
<?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]) ?>
<?= $form->field($model, 'title') ?>
<?= $form->field($model, 'imageFile')->fileInput() ?>
<button type="button" class="btn btn-success subm">Upload</button>
<?php ActiveForm::end(); ?>
<script>
$('.subm').click(function(e){
var formData = new FormData($('form')[0]);
console.log(formData);
$.ajax({
url: "some_php_file.php", //Server script to process data
type: 'POST',
// Form data
data: formData,
beforeSend: beforeSendHandler, // its a function which you have to define
success: function(response) {
console.log(response);
},
error: function(){
alert('ERROR at PHP side!!');
},
//Options to tell jQuery not to process data or worry about content-type.
cache: false,
contentType: false,
processData: false
});
});
</script>
Run Code Online (Sandbox Code Playgroud)
测试
现在通过print_r()如上所示在PHP代码中进行ajax请求和调试,您将注意到它$_FILES不是NULL并且它包含所有文件(需要上载的)数据.如果已设置,您可以使用move_uploaded_file()功能上传
这就是你的文件通过Ajax上传的方式.