How to upload, remove and download files from Microsoft SharePoint using MS Graph API in Laravel

How to upload, remove and download files from Microsoft SharePoint using MS Graph API in Laravel


In this post, you will be learning how to upload a file to Microsoft SharePoint, how to remove or delete a file from Microsoft SharePoint, how to download a file from  Microsoft SharePoint using Microsoft Graph API.

Before we dive into the code, you need to ensure you have the following prerequisites:

The File upload, remove and download are managed from the root directory/folder of Microsoft SharePoint.

Step 1: Create a controller named FileUploadController.php and paste the below code

<?php

namespace App\Http\Controllers\Api\V1;

use App\Models\FileDetail;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use App\Services\MicrosoftGraphService;

class FileUploadController extends Controller
{
    public function store(Request $request)
    {
        if(MicrosoftGraphService::sharepointFileUploadEnabledCheck())
        {
            if($request->hasFile('file')) {

                $file = $request->file('file');

                $user = Auth::user();
                $uploadResponse = MicrosoftGraphService::uploadFileToSharepoint($file, $user->msAccessToken->access_token);

                if ($uploadResponse['status_code'] == 201) {

                    FileDetail::create([
                        'download_url' =>  $uploadResponse['download_url'],
                        'web_url' =>  $uploadResponse['web_url'],
                        'file_type' =>  $uploadResponse['file_type'],
                        'storage_location' =>  $uploadResponse['storage_location'],
                    ]);

                } else {

                    return response()->json([
                        'error' => $uploadResponse['error'],
                        'details' => $uploadResponse['details']
                    ], $uploadResponse['status_code']);
                }
            }
        }
        else
        {
            return response()->json([
                'message' => 'Access token not found',
            ],401);
        }
    }

    public function update(Request $request, $fileUploadId)
    {
        $fileDetail = FileDetail::where('id',$fileUploadId)->first();

        if(MicrosoftGraphService::sharepointFileUploadEnabledCheck())
        {
            if($request->hasFile('file')) {

                //Lets remove the Old file
                if($fileDetail->storage_location == 'sharepoint'){

                    $queryString = parse_url($fileDetail->download_url, PHP_URL_QUERY);
                    parse_str($queryString, $queryParams); // Parse the query string into an array
                    $uniqueId = $queryParams['UniqueId'] ?? null; // Return the UniqueId if it exists

                    if($uniqueId){
                        $user = Auth::user();
                        MicrosoftGraphService::removeFileFromSharepoint($uniqueId, $user->msAccessToken->access_token);
                    }
                }

                //Lets upload with the New file
                $file = $request->file('file');

                $user = Auth::user();
                $uploadResponse = MicrosoftGraphService::uploadFileToSharepoint($file, $user->msAccessToken->access_token);

                if ($uploadResponse['status_code'] == 201) {

                    FileDetail::where('id',$fileDetail->id)->update([
                        'download_url' =>  $uploadResponse['download_url'],
                        'web_url' =>  $uploadResponse['web_url'],
                        'file_type' =>  $uploadResponse['file_type'],
                        'storage_location' =>  $uploadResponse['storage_location'],
                    ]);

                } else {

                    return response()->json([
                        'error' => $uploadResponse['error'],
                        'details' => $uploadResponse['details']
                    ], $uploadResponse['status_code']);
                }
            }
        }
        else
        {
            return response()->json([
                'message' => 'Access token not found',
            ],401);
        }
    }

    public function destroy($fileUploadId)
    {
        $fileDetail = FileDetail::where('id',$fileUploadId)->first();

        try{

            if($fileDetail->storage_location == 'sharepoint'){

                if(MicrosoftGraphService::sharepointFileUploadEnabledCheck())
                {
                    $queryString = parse_url($fileDetail->download_url, PHP_URL_QUERY);
                    parse_str($queryString, $queryParams); // Parse the query string into an array
                    $uniqueId = $queryParams['UniqueId'] ?? null; // Return the UniqueId if it exists

                    if($uniqueId){
                        $user = Auth::user();
                        MicrosoftGraphService::removeFileFromSharepoint($uniqueId, $user->msAccessToken->access_token);
                    }
                }
                else
                {
                    return response()->json([
                        'message' => 'Access token not found',
                    ],401);
                }
            }

            $fileDetail->delete();

            return response()->json([
                'message' => 'File deleted successfully'
            ], 200);

        }catch (\Exception $ex){

            return response()->json([
                'code' => 500,
                'message' => 'Something Went Wrong... Please try again',
                'status' => 'error',
                'error' => $ex->getMessage()
            ], 500);
        }
    }

    public function downloadFile($fileUploadId)
    {
        $fileDetail = FileDetail::where('id',$fileUploadId)->first();
        if ($fileDetail) {

            if($fileDetail->storage_location == 'sharepoint'){

                if(MicrosoftGraphService::sharepointFileUploadEnabledCheck())
                {
                    $user = Auth::user();
                    $downloadResponse = MicrosoftGraphService::downloadFileFromSharepoint($fileDetail->download_url, $user->msAccessToken->access_token);
                    if($downloadResponse['status_code'] == 200){

                        return response($downloadResponse['fileContent'], 200)
                            ->header('Content-Type', $downloadResponse['mimeType'])
                            ->header('Content-Disposition', 'attachment; filename="' . basename($fileDetail->download_url) . '"');
                    }else{
                        return response()->json($downloadResponse, $downloadResponse['status_code']);
                    }

                } else {
                    return response()->json([
                        'message' => 'Access token not found',
                    ],401);
                }
            }

        }else{

            return response()->json([
                'code' => 404,
                'message' => 'No File detail found',
            ], 404);
        }
    }
}

 

Step 2: Create a Service file in following path: app\Services\MicrosoftGraphService.php and paste the below code

<?php

namespace App\Services;

use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Http;
use GuzzleHttp\Client;

class MicrosoftGraphService
{
    public static function uploadFileToSharepoint($file, $msAccessToken)
    {
        $filePath = $file->getPathname();
        $fileName = $file->getClientOriginalName();
        $fileType = $file->getClientOriginalExtension();
        $fileMimeType = $file->getMimeType();

        $fileContent =  file_get_contents($filePath);

        $client = new Client();

        $response = $client->request('PUT', "https://graph.microsoft.com/v1.0/sites/root/drive/root:/{$fileName}:/content", [
            'headers' => [
                'Authorization' => 'Bearer ' . $msAccessToken,
                'Content-Type' => $fileMimeType,
            ],
            'body' => $fileContent,
        ]);

        $responseBody = $response->getBody()->getContents();

        if ($response->getStatusCode() == 201) {
            $responseData = json_decode($responseBody, true);

            $webUrl = $responseData['webUrl'] ?? 'URL not available'; //To view the File on Browser via link

            /**
             * This is the "@microsoft.graph.downloadUrl" (Download_URL) to download any type of file from Sharepoint.
             * Note: In this "@microsoft.graph.downloadUrl", you will have many parameters, but "UniqueId" parameter can be used to delete this file.
             */
            $downloadUrl = $responseData['@microsoft.graph.downloadUrl'];

            return [
                'download_url' => $downloadUrl,
                'web_url' => $webUrl,
                'file_type' => $fileType,
                'storage_location' => 'sharepoint',
                // 'details' => $responseData,
                'stauts_code' => $response->getStatusCode(),
            ];

        } else {

            return [
                'error' => 'Failed to upload file',
                'details' => $responseBody,
                'stauts_code' => $response->getStatusCode(),
            ];
        }
    }

    /**
     *
     * The "UniqueId" is extracted from "@microsoft.graph.downloadUrl" (Download URL) which is a parameter.
     * This parameter "UniqueId" is used for deleting the File from sharepoint.
     */
    public static function removeFileFromSharepoint($uniqueId, $msAccessToken)
    {
        $response = Http::withHeaders([
            'Authorization' => 'Bearer ' . $msAccessToken,
        ])->delete("https://graph.microsoft.com/v1.0/sites/root/drive/items/{$uniqueId}");

        if ($response->successful()) {

            return [
                'message' => 'File deleted successfully!',
                'status' => 'success',
                'status_code' => $response->status(),
            ];
        } else {

            $errorResponse = $response->json();
            return [
                'message' => 'Failed to delete the file.',
                'status' => 'error',
                'error' => $errorResponse,
                'status_code' => $response->status(),
            ];
        }
    }

    public static function downloadFileFromSharepoint($downloadLink, $msAccessToken)
    {
        $client = new Client();

        try {
            $response = $client->request('GET', $downloadLink, [
                'headers' => [
                    'Authorization' => 'Bearer ' . $msAccessToken,
                ],
            ]);

            if ($response->getStatusCode() === 200) {

                $fileContent = $response->getBody()->getContents();
                $mimeType = $response->getHeaderLine('Content-Type');

                return [
                    'fileContent' => $fileContent,
                    'mimeType' => $mimeType,
                    'status_code' => 200
                ];

            } else {
                $errorResponse = $response->getBody()->getContents();
                return [
                    'message' => 'Failed to download file from SharePoint.',
                    'error' => $errorResponse,
                    'status' => 'error',
                    'status_code' => $response->getStatusCode(),
                ];
            }
        } catch (\Exception $e) {

            return [
                'message' => 'An error occurred while attempting to download the file.',
                'error' => $e->getMessage(),
                'status' => 'error',
                'status_code' => 500
            ];
        }
    }

    /**
     * checking if has token and also file-upload to sharepoint is enabled.
     * You can enable from : http://localhost:3000/settings/email/configuration
     */
    public static function sharepointFileUploadEnabledCheck()
    {
        $user = Auth::user();
        if($user->msAccessToken && $user->msAccessToken->is_file_upload_enabled){
            return true;
        }else{
            return false;
        }
    }
}
?>


Step 3: Create a Model related to your requirement. So as I have used in this code its FileDetail.php

php artisan make:model FileDetail -m

with the above command, you will be able to create the Model & Migration file both.

So as per your requirements, please add your fields.


Thanks for reading.