dssj88098 2015-08-09 20:24
浏览 62
已采纳

使用php:// input,PHP AJAX上传无法正常工作

I am trying to use the JavaScript/jQuery Ajax File Uploader by Jordan Feldstein available at https://github.com/jfeldstein/jQuery.AjaxFileUpload.js

It is an older library but still very popular due to it's simplicity and for being so lightweight (around 100 lines) and you can attach it to a single form input filed and it simply works! You select a file as normal with the form inut filed and on selection it instantly uploads using AJAX and returns the uploaded file URL.

This makes the library good for my use where I am uploading a file inside a modal window which is also generate with AJAX and I have used this library in many similar projects.

My backend is using PHP and Laravel and that is where my issue seems to be.

My test script works but when I implement it into my Laravel app it returns this error....

ERROR: Failed to write data to 1439150550.jpg, check permissions

This error is set in my controller below when this code is not retuning a value...

$result = file_put_contents( $folder . '/' .$filename, file_get_contents('php://input') );

So perhaps this part file_get_contents('php://input') does not contain my file data?

It does create the proper directory structure and even a file which is /uploads/backing/2015/08/1439150550.jpg

The 1439150550.jpg is a timestamp of when the upload took place. It create this file in the proper location however the file created has no content and is 0 bytes!

Below is my Laravel Controller action which handles the back-end upload and below that the JavaScript....

PHP Laravel Controller Method:

public function uploadBackingStageOneFile(){
    // Only accept files with these extensions
    $whitelist = array('ai', 'psd', 'svg', 'jpg', 'jpeg', 'png', 'gif');
    $name      = null;
    $error     = 'No file uploaded.';
    $destination = '';


    //DIRECTORY_SEPARATOR
    $utc_str = gmdate("M d Y H:i:s", time());
    $utc = strtotime($utc_str);

    $filename = $utc . '.jpg';
    $folder = 'uploads/backing/'.date('Y') .'/'.date('m');

     //if Directory does not exist, create it
     if(! File::isDirectory($folder)){
        File::makeDirectory($folder, 0777, true);
     }

    // Save Image to folder
    $result = file_put_contents( $folder . '/' .$filename, file_get_contents('php://input') );
    if (!$result) {
        Log::info("ERROR: Failed to write data to $filename, check permissions");
        return "ERROR: Failed to write data to $filename, check permissions
";
    }

    $url = $folder . '/' . $filename;

    return Response::json(array(
        'name'  => $name,
        'error' => $error,
        'destination' => $url
    ));

}

JavaScript AJAX FIle Upload LIbrary

/*
// jQuery Ajax File Uploader
//
// @author: Jordan Feldstein <jfeldstein.com>
//          https://github.com/jfeldstein/jQuery.AjaxFileUpload.js
//  - Ajaxifies an individual <input type="file">
//  - Files are sandboxed. Doesn't matter how many, or where they are, on the page.
//  - Allows for extra parameters to be included with the file
//  - onStart callback can cancel the upload by returning false

Demo HTML upload input
<input id="new-backing-stage-1-file" type="file">

Demo JavaScript to setup/init this lbrary on the upload field  
    $('#new-backing-stage-1-file').ajaxfileupload({
      'action': '/upload.php',
      'params': {
        'extra': 'info'
      },
      'onComplete': function(response) {
        console.log('custom handler for file:');
        alert(JSON.stringify(response));
      },
      'onStart': function() {
        if(weWantedTo) return false; // cancels upload
      },
      'onCancel': function() {
        console.log('no file selected');
      }
    });

*/


(function($) {
    $.fn.ajaxfileupload = function(options) {
        var settings = {
          params: {},
          action: '',
          onStart: function() { },
          onComplete: function(response) { },
          onCancel: function() { },
          validate_extensions : true,
          valid_extensions : ['gif','png','jpg','jpeg'],
          submit_button : null
        };

        var uploading_file = false;

        if ( options ) {
          $.extend( settings, options );
        }


        // 'this' is a jQuery collection of one or more (hopefully)
        //  file elements, but doesn't check for this yet
        return this.each(function() {
          var $element = $(this);

          // Skip elements that are already setup. May replace this
          //  with uninit() later, to allow updating that settings
          if($element.data('ajaxUploader-setup') === true) return;

          $element.change(function()
          {
            // since a new image was selected, reset the marker
            uploading_file = false;

            // only update the file from here if we haven't assigned a submit button
            if (settings.submit_button == null)
            {
              upload_file();
            }
          });

          if (settings.submit_button == null)
          {
            // do nothing
          } else
          {
            settings.submit_button.click(function(e)
            {
              // Prevent non-AJAXy submit
              e.preventDefault();

              // only attempt to upload file if we're not uploading
              if (!uploading_file)
              {
                upload_file();
              }
            });
          }

          var upload_file = function()
          {
            if($element.val() == '') return settings.onCancel.apply($element, [settings.params]);

            // make sure extension is valid
            var ext = $element.val().split('.').pop().toLowerCase();
            if(true === settings.validate_extensions && $.inArray(ext, settings.valid_extensions) == -1)
            {
              // Pass back to the user
              settings.onComplete.apply($element, [{status: false, message: 'The select file type is invalid. File must be ' + settings.valid_extensions.join(', ') + '.'}, settings.params]);
            } else
            {
              uploading_file = true;

              // Creates the form, extra inputs and iframe used to
              //  submit / upload the file
              wrapElement($element);

              // Call user-supplied (or default) onStart(), setting
              //  it's this context to the file DOM element
              var ret = settings.onStart.apply($element, [settings.params]);

              // let onStart have the option to cancel the upload
              if(ret !== false)
              {
                $element.parent('form').submit(function(e) { e.stopPropagation(); }).submit();
              }
            }
          };

          // Mark this element as setup
          $element.data('ajaxUploader-setup', true);

          /*
          // Internal handler that tries to parse the response
          //  and clean up after ourselves.
          */
          var handleResponse = function(loadedFrame, element) {
            var response, responseStr = $(loadedFrame).contents().text();
            try {
              //response = $.parseJSON($.trim(responseStr));
              response = JSON.parse(responseStr);
            } catch(e) {
              response = responseStr;
            }

            // Tear-down the wrapper form
            element.siblings().remove();
            element.unwrap();

            uploading_file = false;

            // Pass back to the user
            settings.onComplete.apply(element, [response, settings.params]);
          };

          /*
          // Wraps element in a <form> tag, and inserts hidden inputs for each
          //  key:value pair in settings.params so they can be sent along with
          //  the upload. Then, creates an iframe that the whole thing is
          //  uploaded through.
          */
          var wrapElement = function(element) {
            // Create an iframe to submit through, using a semi-unique ID
            var frame_id = 'ajaxUploader-iframe-' + Math.round(new Date().getTime() / 1000)
            $('body').after('<iframe width="0" height="0" style="display:none;" name="'+frame_id+'" id="'+frame_id+'"/>');
            $('#'+frame_id).get(0).onload = function() {
              handleResponse(this, element);
            };

            // Wrap it in a form
            element.wrap(function() {
              return '<form action="' + settings.action + '" method="POST" enctype="multipart/form-data" target="'+frame_id+'" />'
            })
            // Insert <input type='hidden'>'s for each param
            .before(function() {
              var key, html = '';
              for(key in settings.params) {
                var paramVal = settings.params[key];
                if (typeof paramVal === 'function') {
                  paramVal = paramVal();
                }
                html += '<input type="hidden" name="' + key + '" value="' + paramVal + '" />';
              }
              return html;
            });
          }



        });
      }
})( jQuery );

My JavaScript usage of the above library:

// When Modal is shown, init the AJAX uploader library  
$("#orderModal").on('shown.bs.modal', function () {

    // upload new backing file
    $('#new-backing-stage-1-file').ajaxfileupload({
      action: 'http://timeclock.hgjghjg.com/orders/orderboards/order/uploadbackingimage',
      params: {
        extra: 'info'
      },
      onComplete: function(response) {
        console.log('custom handler for file:');
        console.log('got response: ');
        console.log(response);
        console.log(this);
        //alert(JSON.stringify(response));
      },
      onStart: function() {
        //if(weWantedTo) return false; // cancels upload
        console.log('starting upload');
        console.log(this);
      },
      onCancel: function() {
        console.log('no file selected');
        console.log('cancelling: ');
        console.log(this);
      }
    });
});
  • 写回答

1条回答 默认 最新

  • douxian5076 2015-08-09 20:50
    关注

    The problem is like you said, file_get_contents('php://input') does not contain your file data.

    jQuery.AjaxFileUpload plugin wrap file input element with a form element that contains enctype="multipart/form-data" attribute. 1

    From php documentation: 2

    php://input is not available with enctype="multipart/form-data".

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 深度学习根据CNN网络模型,搭建BP模型并训练MNIST数据集
  • ¥15 lammps拉伸应力应变曲线分析
  • ¥15 C++ 头文件/宏冲突问题解决
  • ¥15 用comsol模拟大气湍流通过底部加热(温度不同)的腔体
  • ¥50 安卓adb backup备份子用户应用数据失败
  • ¥20 有人能用聚类分析帮我分析一下文本内容嘛
  • ¥15 请问Lammps做复合材料拉伸模拟,应力应变曲线问题
  • ¥30 python代码,帮调试,帮帮忙吧
  • ¥15 #MATLAB仿真#车辆换道路径规划
  • ¥15 java 操作 elasticsearch 8.1 实现 索引的重建