XMLHttpRequest - Laravel

3

我正在使用 Laravel 上传文件,并使用 AJAX 请求来创建进度条。以下是表单的操作路由,指向控制器:

<form action="{{ URL::route('upload-file-form-post') }}" method="POST" enctype="multipart/form-data">
.
.
</form>

ajax:

function _(el) {
    return document.getElementById(el);
}

function uploadfile() {
  var file = _("file").files[0];
  // dev
  alert(file.name+" | "+file.size+ " | "+" | "+file.type);
  var formdata = new FormData();
  formdata.append("file", file);
  var ajax = new XMLHttpRequest();
  ajax.upload.addEventListener("progress", progressHandler, false);
  ajax.addEventListener("load", completeHandler, false);
  ajax.open("POST", "here_is_where_the_url_needs_to_go");
  ajax.send(formdata);
}

function progressHandler(event) {
   _("loaded_n_total").innerHTML = "Uploaded " + event.loaded + "bytes of "+ event.total;
   var percent = (event.loaded / event.total) * 100;
   _("progressBar").value = Math.round(percent);
   _("status").innerHTML = Math.round(percent)+"% uploaded... please wait";
}

function completeHandler(event) {
  _("status").innerHTML = event.target.responseText;
  _("progressBar").value = 0;
} 

有没有办法将此代码 {{ URL::route('upload-file-form-post') }} 发送到 ajax 请求中?

在我的路由文件中,以上内容被引用为:

Route::post('/asset/upload-file', array(
    'as'  => 'upload-file-form-post',
    'uses' => 'AssetController@postUploadCreate'
));

你的AJAX代码真的是全局的(直接在<script>标签内部)吗?还是在事件中触发的?比如表单被提交?这将使得获取action更容易。 - Ian
完整的JS代码已更新,它将在单击事件onclick="uploadfile()"触发。 - cch
你想在你的js代码中使用url/route吗?加载这个页面的是哪个view - The Alpha
@cchacholiades onclick 事件绑定在哪个元素上? - Rahil Wazir
<input type="submit" value="Upload file" onclick="uploadfile()">。加载此页面的视图?我不确定你问我的是什么,它是一个扩展主要 Blade 布局的视图。 - cch
是的,我想在JS代码中使用URL/路由。 - cch
1个回答

5

只需使用JavaScript获取表单操作属性

//Whatever your action value
var action = document.formName.getAttribute('action');

第一点:

不要在提交按钮上混合使用onclick事件,点击提交按钮实际上处理的是表单本身。最好绑定表单的提交事件,而不是在提交按钮上绑定点击事件。

通过给表单添加一个name属性,比如name="my_form",您可以为表单添加提交事件处理程序。

像这样:

document.my_form.addEventListener('submit', function(e) {
    e.preventDefault();

    var actionURL = this.action; // will get the form action url
    uploadfile(actionURL); // your upload event with request url
});

您的函数uploadfile(..)将接受一个名为URL的参数。该参数将传递给ajax.open(..)方法。
// -----------------!!!! pass parameter for url
function uploadfile(url) {
  var file = _("file").files[0];
  // dev
  alert(file.name+" | "+file.size+ " | "+" | "+file.type);
  var formdata = new FormData();
  formdata.append("file", file);
  var ajax = new XMLHttpRequest();
  ajax.upload.addEventListener("progress", progressHandler, false);
  ajax.addEventListener("load", completeHandler, false);
  ajax.open("POST", url); // your url will pass to open method
  ajax.send(formdata);
}

编辑:

为了解决 Laravel 不匹配的令牌问题 (参考)

在当前表单视图文件的<head>标签中添加下面的<meta >标签。

<meta name="csrf-token" content="<?php echo csrf_token() ?>">

或者使用Blade。
<meta name="csrf-token" content="{{{ csrf_token() }}}">

现在,在您的uploadfile(...)函数中添加以下代码片段:
var metas = document.getElementsByTagName('meta'); 

for (i=0; i<metas.length; i++) { 
    if (metas[i].getAttribute("name") == "csrf-token") {  
        ajax.setRequestHeader("X-CSRF-Token", metas[i].getAttribute("content"));
    } 
}

请查看此示例中更新的JavaScript代码。

@cchacholiades 它只会提交一次表单。顺便看看我的编辑。 - Rahil Wazir
未捕获的 InvalidStateError 错误: 无法执行 'XMLHttpRequest' 上的 'setRequestHeader': 对象状态必须是已打开。 这是因为我将 meta 标签添加到了 main.blade.php 中而不是当前视图吗? - cch
1
@cchacholiades 将 for 循环放在 ajax.open(..) 方法之后。请参见更新的 fiddle - Rahil Wazir
@cchacholiades 这是正确的。函数内的 url 只是一个占位符。 - Rahil Wazir

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接