Search code examples
phpcurllaravel-5.1guzzlebox

How to upload files with Guzzle (OAuth 2)


I'm trying to upload files using Guzzle HTTP client and send it to the API URL. However, I couldn't get success over this. I can use Curl however, I want to use Guzzle. I couldn't figure out where to add the uploading files with the Guzzle and how to use the attributes. Here's the relevant Curl code:

curl https://upload.box.com/api/2.0/files/content \
  -H "Authorization: Bearer ACCESS_TOKEN" -X POST \
  -F attributes='{"name":"tigers.jpeg", "parent":{"id":"11446498"}}' \
  -F [email protected]

Here's the reference API docs which I hope you'll find helpful. I'm using Laravel 5.

No matter what I do everytime I'm getting Method not allowed response. Here's the following code I'm trying:

$client = new Client();
        $sendRequest = $client->post('https://upload.box.com/api/2.0/files/content', [], [
            'request.options' => [
                'headers' => [
                    'Authorization' => 'Bearer ' . $access_token
                ]
            ],
            'file' => '/picture.jpg'
        ]);
        $sendRequest->setBody('{"attributes": {"name": "picture.jpg", "parent": {"id": "5605448193"}}}');
try {
    $response = $sendRequest->send();
    dd($response);
} catch(BadResponseException $e) {
        dd($e->getResponse());
    }

Solution

  • I've figured it out myself. Here's the relevant code (full Controller method) which I hope you may find helpful in one day:

    public function store(Request $request)
        {
            if ($request->hasFile('file')) {
                $api = Api::latest()->take(1)->get();
                $access_token = $api[0]->access_token;
                if(Auth::user()->role == 'Administrator') {
                    $folder_id = $request->input('folder_id');
                } elseif(Auth::user()->role == 'Subscriber') {
                    $folder_id = Auth::user()->folder_id;
                }
                $client = new Client();
                $apiRequest = $client->post('https://upload.box.com/api/2.0/files/content');
                $apiRequest->setHeaders([
                    'Authorization' => 'Bearer ' . $access_token,
                    'Content-Type' => 'multipart/form-data'
                ]);
                $apiRequest->setPostField('filename', $request->file('file')->getClientOriginalName());
                $apiRequest->setPostField('parent_id', $folder_id);
                $apiRequest->addPostFile(
                    'file', $request->file('file')->getRealPath(),
                    $request->file('file')->getClientMimeType(),
                    $request->file('file')->getClientOriginalName()
                );
                try {
                    $sendRequest = $apiRequest->send();
                    if ($sendRequest->isSuccessful()) {
                        return redirect()->back()->with('fileUpload', trans('Your file has been uploaded successfully'));
                    }
                } catch (BadResponseException $e) {
                    $result = $e->getResponse()->getStatusCode();
                    if ($result === 401) {
                        $this->regenerate_access_token();
                        $api = Api::latest()->take(1)->get();
                        $access_token = $api[0]->access_token;
                        $client = new Client();
                        $apiRequest = $client->post('https://upload.box.com/api/2.0/files/content');
                        $apiRequest->setHeaders([
                            'Authorization' => 'Bearer ' . $access_token,
                            'Content-Type' => 'multipart/form-data'
                        ]);
                        $apiRequest->setPostField('filename', $request->file('file')->getClientOriginalName());
                        $apiRequest->setPostField('parent_id', Auth::user()->folder_id);
                        $apiRequest->addPostFile(
                            'file', $request->file('file')->getRealPath(),
                            $request->file('file')->getClientMimeType(),
                            $request->file('file')->getClientOriginalName()
                        );
                        $sendRequest = $apiRequest->send();
                        if ($sendRequest->isSuccessful()) {
                            return redirect()->back()->with('fileUpload', trans('Your file has been uploaded successfully'));
                        }
                    } elseif ($result === 409) {
                        return redirect()->back()->with('fileUpload', trans('You have already a file with the same name. Please, rename your file to successful upload'));
                    }
                }
            } else {
                return redirect()->back()->with('fileUpload', trans('Please, select a file to upload'));
            }
        }
    

    Here's the file upload form which should be in your view directory:

    <form action="/store" method="post" enctype="multipart/form-data">
        {{ csrf_field() }}
    
        <div class="row">
            @can('viewElements', \Illuminate\Support\Facades\Auth::user())
            <div class="input-field col s3">
                <select name="folder_id" id="folder_id">
                    <option value="" disabled selected>Choose User</option>
                    @foreach($users as $user)
                        <option value="{{ $user->folder_id }}">{{ $user->name }}</option>
                    @endforeach
                </select>
            </div>
            @endcan
    
            <div class="col {{ $class }}">
                <div class="file-field input-field">
                    <div class="btn">
                        <span>File</span>
                        <input type="file" name="file" required>
                    </div>
    
                    <div class="file-path-wrapper">
                        <input type="text" class="file-path validate" placeholder="Upload your file">
                    </div>
                </div>
            </div>
            <div class="col s3">
                <button class="btn waves-effect waves-light" type="submit">Submit <i class="material-icons right">send</i></button>
            </div>
        </div>
    </form>