File upload is not correctly uploading via API

Hello

I want to upload a hello.docx file to Workspace in folder 10 via API via PHP

This is my script:

<?php

// API endpoint URL
$api_url = 'https://of.mydomain.com/api/2.0/files/10/file';

// Path to the file you want to upload
$file_path = 'hello.docx';

// API Authorization token
$auth_token = 'zLT2qX6/Dxgwqny9+9ZqkEvY/5DxS9GiaKe1u/15BJ4rtdVuvfAvVSrwnjEAHG76LG/W4LP1S4Qy+KxKVxYiZSbzwSP7fab32H7IBFa4FniirPbgdkViJRlYTt7drE5OTrHLxQWzag06EXNiuYxUnQ==';

// JSON data (createNewIfExist, keepConvertStatus)  -- REMOVED title
$json_data = array(
    "createNewIfExist" => array(true),
    "keepConvertStatus" => true
);

// Check if the file exists
if (!file_exists($file_path)) {
  die("Error: File not found at " . $file_path);
}

// Create a CURL resource
$ch = curl_init();

// Configure CURL options

// Set the API URL
curl_setopt($ch, CURLOPT_URL, $api_url);

// Set to POST request
curl_setopt($ch, CURLOPT_POST, 1);

// Prepare the multipart/form-data fields

//IMPORTANT: File name should match what API expects
$file_data = array('file' => new CURLFile(realpath($file_path), mime_content_type($file_path), basename($file_path)));

//Merge the file data and JSON data; the JSON data must be flattened!
//DO NOT flatten the file data!
$post_fields = array_merge($json_data, $file_data);

curl_setopt($ch, CURLOPT_POSTFIELDS, $post_fields);

// Set the authorization header
$headers = array(
    'Authorization: ' . $auth_token,
    'Accept: application/json'
);

curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

// Set to return the response as a string
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

// Optional:  Verify SSL certificate (set to false for testing, but not recommended for production)
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

// Execute the CURL request
$response = curl_exec($ch);

// Check for errors
if (curl_errno($ch)) {
    echo 'CURL Error: ' . curl_error($ch);
} else {
    // Display the API response
    echo "API Response:\n";
    echo $response;
}

// Close the CURL resource
curl_close($ch);

?>

It successfully execute the script but creates a document called : New Document.docx

Why is that? and how can i fix that so that it will upload the correct file?

Hello Guys,

I have ONLYOFFICE Workspace Community running on ubuntu 22.04 for a year now (NON-Docker Version) And everything was running fine TILL yesterday.

I will explain my setup:

SERVER A = PHP WebServer
SERVER B = OnlyOffice Workspace

On server A there will be a XLSX file generated and it will be uploaded to SERVER B via a JWT TOKEN.

This script was uploading the file to (server B) the OnlyOffice Workspace succesfully:


<?php

// UPLOAD XLSX TO SERVER B
$token = "MyTokenHere=";
$apiUrl = "https://office.mydomain.com/api/2.0";

// Authenticate and get a token
function authenticate($apiUrl, $authCredentials) {
    $authEndpoint = "$apiUrl/authentication.json";

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $authEndpoint);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, ["Content-Type: application/json"]);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($authCredentials));

    $response = curl_exec($ch);
    if (curl_errno($ch)) {
        throw new Exception("Curl error: " . curl_error($ch));
    }

    curl_close($ch);
    $data = json_decode($response, true);

    if (!isset($data["response"]["token"])) {
        throw new Exception("Authentication failed. Response: " . $response);
    }

    return $data["response"]["token"];
}

// Upload file
function uploadFile($apiUrl, $folderId, $filePath, $token) {
    $uploadEndpoint = "$apiUrl/files/$folderId/upload";

    if (!file_exists($filePath)) {
        throw new Exception("File not found: $filePath");
    }

     $originalFileName = basename($filePath); // Extract original file name
    // Use preg_replace with a limit of 1 for the first underscore
    $fileName = preg_replace('/_/', ' ', $originalFileName, 1);

    // Use preg_replace with a limit of 1 and offset
    $fileName = preg_replace('/_/', '    ', $fileName, 1);


    $fileInfo = new CURLFile($filePath, mime_content_type($filePath), $fileName);  // Attach the file and set the MIME type (using modified name)

    // Prepare POST data with the file
    $postData = [
        "file" => $fileInfo, // Attach the file
        "title" => $fileName  // Explicitly set the file name (with spaces)
    ];

    // Initialize the cURL request
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $uploadEndpoint);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        "Authorization: Bearer $token",
    ]);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);

    // Execute the request
    $response = curl_exec($ch);
    if (curl_errno($ch)) {
        throw new Exception("Curl error: " . curl_error($ch));
    }

    curl_close($ch);
    $data = json_decode($response, true);

    if (!isset($data["response"])) {
        throw new Exception("File upload failed. Response: " . $response);
    }

    return $data["response"];
}

?>

But since yesterday it stopped with uploading the generated files to SERVER B.
I have checked the logs and i see this error:

2025-06-19 11:52:48,750 **WARN** [327] localhost - ASC.Core - Can not decrypt cookie: Bearer MyTokenHere= from 192.99.167.110 for https://office.mydomain.com/api/2.0/files/62/upload

Is my JWT token expired? How can i check the expire date of the JWT token?
Do i need to generate a NEW token? If yes, how can i do that?

Extra info in the logs:

2025-06-20 11:52:48,750 ERROR [327] localhost - ASC.Core - Authenticate error: cookie Bearer+MyTokenHere=, tenant -1, userid 00000000-0000-0000-0000-000000000000, indexTenant 0, expire 9999-12-31 23:59:59,999, loginEvent 0: System.FormatException: The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or an illegal character among the padding characters.
  at System.Convert.FromBase64CharPtr (System.Char* inputPtr, System.Int32 inputLength) [0x0004c] in <f2b3ab7dfff746f594d2ef5b16ec3c90>:0 
  at System.Convert.FromBase64String (System.String s) [0x00025] in <f2b3ab7dfff746f594d2ef5b16ec3c90>:0 
  at ASC.Security.Cryptography.InstanceCrypto.Decrypt (System.String data) [0x00005] in <b8f2e14ef8fc44438f36ab1c8fda8497>:0 
  at ASC.Core.Security.Authentication.CookieStorage.DecryptCookie (System.String cookie, System.Int32& tenant, System.Guid& userid, System.Int32& indexTenant, System.DateTime& expire, System.Int32& indexUser, System.Int32& loginEventId) [0x0004a] in <df66cb1eb8004178b7eb5e6ae3bb4aaf>:0

P.S my token looks something like this:

tIdn+eWAORELyt1AR9gYegipo2rr1xlQS4rwm6YK68wp0HNxxSfYiDpTDlWlggz1kVUQDoOOBHJVQuqoUDi0JFnaL8FxpgfRAJ4Vo5EBKp1qM1P+QLnbc1BCxx6rO16SeIOnb3joZf+aK+nf/aUafjVo1MsaJyIqB77yqRZCKKA=

It’s not the original token, i have modified it a little bit

Hello @h3llo

Try using Insert method instead:

Hi @Constantine
Thanks for you reply and help

I tried to used the insert method:

<?php

// Configuration - Replace with your actual values
$apiUrl = 'https://of.mydomain.com/api/2.0/files'; // Your API URL (base URL only)
$jwt_secret = 'zLT2qX6\/Dxgwqny9+9ZqkEvY\/5DxS9GiaKe1u\/15BJ4rtdVuvfAvVSrwnjEAHG76LG\/W4LP1S4Qy+KxKVxYiZSbzwSP7fab32H7IBFa4FniirPbgdkViJRlYTt7drE5O7HXcVHsSqwJOWv0ZfXmlvRQVALyAr64L1Jt\/ZlrFAKU='; // Your JWT secret key
$folderId = 10; // Target folder ID
$filePath = '/home/hello.docx'; // Path to your local file
$fileName = basename($filePath); // Extract filename from path
$createNewIfExist = true;  // Whether to create a new file if one with the same name exists.
$keepConvertStatus = true; //  Keep the convert status (set to false if you don't need it).

// Function to generate a JWT token (you might already have this)
function generateJWT($payload, $secret) {
    $header = json_encode(['typ' => 'JWT', 'alg' => 'HS256']);
    $payload = json_encode($payload);

    $base64UrlHeader = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($header));
    $base64UrlPayload = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($payload));

    $signature = hash_hmac('sha256', $base64UrlHeader . '.' . $base64UrlPayload, $secret, true);
    $base64UrlSignature = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($signature));

    return $base64UrlHeader . '.' . $base64UrlPayload . '.' . $base64UrlSignature;
}


// 1.  Prepare the API URL
$uploadUrl = $apiUrl . '/' . $folderId . '/insert';


// 2. Prepare the data for the API request.  Crucially,  the 'file' parameter MUST be null.
$data = [
    'file' => null, // Important: Set to null
    'title' => $fileName,  // Or a custom title if desired
    'createNewIfExist' => [$createNewIfExist], // Wrap boolean value in an array
    'keepConvertStatus' => $keepConvertStatus
];

$jsonData = json_encode($data);



// 3. Generate JWT token for authorization
$token = generateJWT(['payload' => []], $jwt_secret);  // Create a simple payload (or empty).


// 4.  Set up cURL for the upload
$curl = curl_init();

curl_setopt_array($curl, [
    CURLOPT_URL => $uploadUrl,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,  //  Use POST
    CURLOPT_POSTFIELDS => $jsonData,  // Send the JSON data
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/json',
        'Accept: application/json',
        'Authorization: Bearer ' . $token  // Include the JWT token
    ],
    CURLOPT_SSL_VERIFYPEER => false, //  Disable SSL verification (for testing ONLY - remove in production!)
    CURLOPT_SSL_VERIFYHOST => false, //  Disable SSL verification (for testing ONLY - remove in production!)
]);


// 5. Execute the API request
$response = curl_exec($curl);

// Check for cURL errors
if (curl_errno($curl)) {
    echo 'cURL error: ' . curl_error($curl);
    exit;
}

$httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);

curl_close($curl);


// 6. Handle the API response
echo "HTTP Code: " . $httpCode . "\n";
echo "API Response:\n";
echo $response . "\n";



//  7.  If the upload was successful (HTTP 200), trigger the file upload separately

if ($httpCode == 200) {

    $response_data = json_decode($response, true);

        // Extract the upload URL from the insert response. Error handling is crucial here!
    if (isset($response_data['response']['file']['uploadUri'])) {
      $uploadUri = $response_data['response']['file']['uploadUri'];

      echo "Proceeding to upload file to: " . $uploadUri . "\n";


      // Second cURL request for the actual file upload

        $fileCurl = curl_init();

        curl_setopt_array($fileCurl, [
            CURLOPT_URL => $uploadUri,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => file_get_contents($filePath),
            CURLOPT_HTTPHEADER => [
                'Content-Type: application/octet-stream',  // Important for raw file uploads
                'Authorization: Bearer ' . $token   // Include JWT token
            ],
            CURLOPT_SSL_VERIFYPEER => false, //  Disable SSL verification (for testing ONLY - remove in production!)
            CURLOPT_SSL_VERIFYHOST => false, //  Disable SSL verification (for testing ONLY - remove in production!)
        ]);

        $fileUploadResponse = curl_exec($fileCurl);

        if (curl_errno($fileCurl)) {
          echo 'File upload cURL error: ' . curl_error($fileCurl);
        }

        $fileUploadHttpCode = curl_getinfo($fileCurl, CURLINFO_HTTP_CODE);
        curl_close($fileCurl);

        echo "File Upload HTTP Code: " . $fileUploadHttpCode . "\n";
        echo "File Upload API Response:\n";
        echo $fileUploadResponse . "\n";

        if ($fileUploadHttpCode != 200){
            echo "File upload failed.\n";
        } else {
            echo "File uploaded successfully!\n";
        }


    } else {
      echo "Error: Could not extract upload URI from initial API response.\n";
      print_r($response_data); // Print the decoded response for debugging
    }


} else {
    echo "Initial API request failed.  Check the error messages above.\n";
}


?>

But that gives me:

HTTP Code: 401 API Response: Unauthorized Initial API request failed. Check the error messages above.

can you help me how i can successful upload/insert the file?