如何在 laravel 4.2 中使用带有自定义预过滤器的 AJAX 上传 CSV 文件

Posted

技术标签:

【中文标题】如何在 laravel 4.2 中使用带有自定义预过滤器的 AJAX 上传 CSV 文件【英文标题】:How to upload a CSV file using AJAX with custom prefilter in laravel 4.2 【发布时间】:2016-01-22 19:48:07 【问题描述】:

我正在使用 laravel 4.2,目前我不知道如何使用 AJAX 将 csv 文件保存到 public\csv\ 目录中。我仍在寻找一些答案。也许有人可以帮助我。

这是我的代码:

在刀片视图中:

 Form::open(['route' => 'file_upload', 'files' => true, 'id' => 'upload_form', 'method' => 'POST'])
    Form::file('csv_upload', ['id' => 'uploaded_file', 'accept' => 'text/csv'])
    Form::submit('submit', ['class' => 'btn btn-primary btn-xs', 'id' => 'upload'])
 Form::close()

javascript Ajax:

var ajax_ready = 1
var token = Session::get('_token')

if($.type(originalOptions.data) === 'string') 
              options.data = originalOptions.data+"&_token="+token;
 else if($.type(originalOptions.data) === 'object') 
         //Here I got a new error
 else
     options.data = $.param(($.extend(originalOptions.data, '_token':mmad_token)));
 

 options.url = originalOptions.url.slice(0,originalOptions.url.indexOf("?_token="));

   if (ajax_ready!=1)
              jqXHR.abort();
   
  ajax_ready = 0;
);
$('form#upload_form').on('submit', function(e)
    e.preventDefault();
    var uploadFile =  $('#uploaded_file');

    var ext = $("input#uploaded_file").val().split(".").pop().toLowerCase();
    var file = $('input[name="csv_upload"]').val();

    if($.inArray(ext, ["csv"]) === -1) 
             alert("Please upload a .csv file!");
             return false;
    

     var csv = uploadFile[0].files;
     var form = new FormData(this);

     var csvFile = lastModifed: csv[0].lastModified, fileName: csv[0].name, size: csv[0].size, fileType: csv[0].type;

      $.post(' URL::route("file_upload") ?_token=Session::token()',
           data: form
      ).done(function(response)

      );

);

php

public function upload_csv()

    $inputs = Input::all();

    $csvFile = $inputs['data']['fileName'];

    $path = public_path().DIRECTORY_SEPARATOR.'csv'.DIRECTORY_SEPARATOR;
    $path2 = public_path('csv/');

    if(is_dir($path2))
    
        @move_uploaded_file($csvFile, $path2.$csvFile); //This line can't move the uploaded files in my desired directory
    

    return json_encode(['success' => 1, 'description' => 'Successfully Upload File']);


以下代码在不使用 AJAX 时确实有效:

  if(Input::hasFile('csv_upload'))
    
        $file = Input::file('csv_upload');

        $originalFilename = $file->getClientOriginalName();

        $rules = ['csv_upload' => 'required|file:csv'];

        $validate = Validator::make(['csv_upload' => $file], $rules);

        if($validate->fails())
        
            return json_encode(['error' => 1, 'description' => 'File must be in .csv format']);
        

        $path = public_path('/csv/');

        if(!file_exists($path))
        
            mkdir($path);
        
     

csv 的控制台日志

【问题讨论】:

你不认为你需要通过 csrf 令牌...afaik 你需要通过 我将更新我的问题,因为我目前将 csrf 令牌与 url 一起发送。 为什么不使用 plupload 库,它可以将文件发布到您的 url。它将与您现有的控制器一起使用。 其他代码工作正常,但使用 ajaxprefilter 但包含时我不知道接受自定义请求。 【参考方案1】:

要将上传的文件移动到新位置,您应该使用 move 方法。此方法会将文件从其临时上传位置(由您的 PHP 配置确定)移动到您选择的更永久的目的地:

Input::file('fileName')->move($destinationPath, $fileName);

如果您需要额外的验证,可以在http://laravel.com/docs/5.1/requests#files查看它

【讨论】:

是的,但我就是这样做的。仍然无法正常工作,所以我选择上传文件的本机。 请求参数是ajax格式。问题是如果我做 ajax 上传的文件没有存储到临时文件中。 你在 laravel 中获取文件对象吗?检查this solution 不,我得到了一个对象数组。在上图中 当我使用FormData() 然后通过ajax的数据传递它。我得到非法调用。【参考方案2】:

您不能移动文件,因为当您使用 ajax 提交表单时 文件没有被发送 使用 ajax,要发送文件,您必须使用 FormData() javascript 发送文件对象。

如果您通过输入print_r($_FILES); 签入upload_csv 控制器,您将得到空数组。

所以在客户端使用FormData 附加文件,然后尝试agian。 您没有收到错误,因为您使用了 php 错误控制运算符 likes@move_uploaded_file($csvFile, $path2.$csvFile);

如果您需要工作示例,请告诉我,我会给您。

为您提供帮助的代码: 1. 在刀片视图中:

  <script type="text/javascript">
     $('form#upload_form').on('submit', function(e)
        e.preventDefault();
        var uploadFile =  $('#uploaded_file');

        var ext = $("input#uploaded_file").val().split(".").pop().toLowerCase();
        var file = $('input[name="mmad_csv_upload"]').val();

        if($.inArray(ext, ["csv"]) === -1) 
                 alert("Please upload a .csv file!");
                 return false;
        
        var csv = uploadFile[0].files;
        var formData = new FormData($(this)[0]);
        formData.append('uploaded_file', $("#uploaded_file")[0].files[0]);
        formData.append('lastModifed', csv[0].lastModified);
        formData.append('fileName', csv[0].name);
        console.log(formData);


        $.ajax(
        url: ' URL::route("file_upload") ',
        type: 'POST',
        data: formData,
        async: true,
        cache: false,
        contentType: false,
        processData: false,
        success: function (returndata)  //alert(returndata); return false;

        
        );      

    );
 </script>

2.控制器

public function file_upload(Request $request)

    $inputs = Input::all();
    $csvFile = $inputs['fileName'];


    $path = public_path().DIRECTORY_SEPARATOR.'csv'.DIRECTORY_SEPARATOR;
    $path2 = public_path('/csv/');
    if(is_dir($path2))
    
        $success = $request->file('uploaded_file')->move($path2, $csvFile);
    
    return json_encode(['success' => 1, 'description' => 'Successfully Upload File']);


【讨论】:

你能给我吗?我想使用Input::file('filename') 获取数据文件 我已经编辑了我的答案并添加了代码。请检查。 好的,我明天试试。 它说是Error: Illegal invocation 你已经使用了 jQuery 的 $.post() 函数,而不是你必须为 formdata() 使用 $.ajax 函数,你改变了那个。你得到非法调用是因为 jQuery 试图序列化 $.post 的 jQuery 对象,但它不能。它可能试图调用一个字符串方法,并将一个 jQuery 对象作为上下文传递给它,从而导致错误。【参考方案3】:

默认 AJAX POST 不支持文件上传。使用 jQuery Form 成功上传文件。文件上传的完整文档http://malsup.com/jquery/form/#file-upload

下面是我最近构建脚本的示例...我的控制器将文件上传到 S3,但很容易使用本地存储实现。

var progress = function(event, position, total, percent) 
    $(".progress-bar").width(percent + '%');
    $(".progress-bar").html(percent + '%');
    if(percent > 50) 
        $(".progress-bar").css('color','#fff');
    
    if(percent == 100) 
        setTimeout(function()
            $(".progress").html('<span class="processing-msg">Processing... Please be patient!</span>');
            $(".processing-msg").fadeIn('slow');
        , 1000);
    


var success = function(data) 
    var obj = $.parseJSON(data);
    $("#"+obj.hidden, parent.document).val(obj.filename);
    var src = 'https://s3.amazonaws.com/spincms'+obj.path+'thumb_'+obj.filename;
    $("#uploaded-"+obj.hidden, parent.document).html('<img class="img-circle uploaded-img" src="' + src + '">');
    $(".progress").html('<span class="processing-msg-next">File has been uploaded and processed. Do not forget to submit the form!</span>');


var options = 
    target: '#output',
    uploadProgress: progress,
    success: success,
    resetForm: true
;

$(document).on('click', "#upload-now", function(e) 
    $(".progress").html('<div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100"></div>');
    if($("#upload-form input[type=file]")[0].files.length == 0) 
        $(".progress").html('<span class="processing-msg-next">No file selected!</span>');
        return false;
     else 
        var name = $("#upload-form input[name='name']").val();
        var token = $("#upload-form input[name='_token']").val();
        var file_name = $("#upload-form input[type=file]")[0].files[0].name;
        $("#upload-form").ajaxSubmit(options);
        
    
);

【讨论】:

有什么比@aldrin27 更好的解决方案? *** 的整个想法是分享结果和/或将答案标记为解决方案......谢谢【参考方案4】:

由于您使用的是 jQuery,因此您可以使用 form plugin,因为它会让您更轻松地使用它,例如,这是您将使用的 jquery 部分:

$(document).ready(function()  
    // bind 'myForm' and provide a simple callback function 
    $('#upload_form').ajaxForm(function()  
        alert("Your file has been uploaded, thanks"); 
    ); 
); 

在您的控制器中,您可以像这样编写代码:

pubilc function postUpload()

    $success = false;
    if(Request::ajax())
    
        if(Input::hasFile('csv_upload'))
        
            $file = Input::file('csv_upload');
            if(!File::isDirectory(storage_path('csv'))) 
                File::createDirectory(storage_path('csv'));
            

            $file->move(storage_path('csv'), $file->getClientOriginalName());
            // now your file is on app/storage/csv folder
            $filePath = storage_path('csv/'.$file->getClientOriginalName());
            $success = true;
           
    


    return Response::json(['success'=>$success]);

【讨论】:

以上是关于如何在 laravel 4.2 中使用带有自定义预过滤器的 AJAX 上传 CSV 文件的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Laravel 4.2 中创建自定义 DB Query Builder 方法

如何将控制器中的 Laravel 4.2 beforeFilter 转换为 Laravel 5.2 中的自定义中间件

Laravel 4.2 视图:从自定义位置发布

Laravel:如何设置带有条件的自定义列?

如何使用带有自定义用户名列的 Laravel Passport

Laravel 使用自定义查询预加载嵌套关系