alexpgates
3 years ago
3385
3
Requests

Uploading files via Laravel API

Posted 3 years ago by alexpgates

I'm attempting to use auth:api middleware in Laravel 5.2 to accept a POST from a remote server which contains form data + an image file.

I have everything working nicely using Intervention\Image\ImageServiceProvider through the regular web middleware, but unfortunately I'm having some issues with my approach through the API because I'm not able to access EXIF data from my base64'd image.

I'm beginning to think I need to rethink my approach, but I'm not quite sure what I'm missing.

The following works - it's just that I can't call orientate() on my image because Image object must be instantiated from file path to read the EXIF data correctly for orientate() to work properly.

On my remote site, I'm passing along the submitted form data like this:

<?php 
    $data = $_POST;
    $data['api_token'] = 'myapitokenisheremyapitokenisheremyapitokenisheremyapitokenishere';
    if(isset($_FILES['image'])){
        // we have an image, get the image data
        $data['image'] = base64_encode(file_get_contents($_FILES['image']['tmp_name']));
    }
    $json_data = json_encode($data);
    $ch = curl_init();

    curl_setopt($ch, CURLOPT_URL,"http://my-site.dev/api/v1/alumni/add");
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $json_data);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(                                                                          
        'Content-Type: application/json',
        'Accept: application/json',                                                                            
        'Content-Length: ' . strlen($json_data))                                                                       
    ); 

    $api_result = curl_exec ($ch);
    // $api_result 'success' if successful!

    curl_close ($ch);
 ?>

My routes.php looks like

Route::group(['prefix' => 'api/v1', 'middleware' => 'auth:api'], function () {

    Route::post('alumni/add', 'APIController@store');

});

My controller:

         public function store(StudentRequest $request)
    {
        $student = Student::create($request->all());

        // do we have an image to process?
        if($request->image){
            //$filename = substr( md5( $student->id . '-' . time() ), 0, 15) . '.' . $request->file('image')->getClientOriginalExtension();
            $filename = $student->id.'-'.substr( md5( $student->id . '-' . time() ), 0, 15) . '.jpg'; // for now just assume .jpg : \
            $path = public_path('alumni-photos/' . $filename);
            Image::make($request->image)->orientate()->fit(500)->save($path);

            // now update the photo column on the student record
            $student->photo = $filename;
            $student->save();
        }

        return 'success';
    }

So on my remote site, I'm checking for the presence of a $_FILES and base64_encoding() the file from the tmp path.

In my controller, I'm checking for $request->image and using that in Image::make() to create my image.

There are a couple issues with this.

  • I'm not able to use hasFile('image') which probably isn't a huge deal, but that means I can't use $request->file('image')->getClientOriginalExtension() to get the file extension.
  • Since I'm not instantiating my image from a file (and instead passing in base64'd data) I can't call orientate() on the image, which leaves me with upside down images half of the time.

I'm thinking there must be a way to do this without having to pass along base64_encode()'d data, but whenever I try to pass along anything that isn't 'Content-Type: application/json', from my remote server, I'm hit with a 401.

Any guidance would be appreciated!

Please sign in or create an account to participate in this conversation.