How to send data to GAS function?

I am using Google Apps Script to write a small web app where I can upload an image (Business Cards) which is then stored in my Google Drive.
The image should be utilized by ChatGPT which extract the information and save them into Google Spreadsheets.

I have this Index.html where I can select and image and upload it. It saved to my Google Drive successfully but I get an error Uncaught at uploadImageToServer (Code:34).

Here is the HTML

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <style>
      #status {
        margin-top: 10px;
        font-weight: bold;
      }
    </style>
  </head>
  <body>
    <form id="uploadForm">
      <input type="file" id="fileInput" accept="image/*">
      <input type="button" value="Upload" onclick="uploadImage()">
    </form>
    <pre id="result"></pre>
    <div id="status"></div>
    <script>
      function uploadImage() {
        const fileInput = document.getElementById('fileInput');
        const file = fileInput.files[0];
        const statusDiv = document.getElementById('status');

        if (!file) {
          alert("Please select a file before uploading.");
          return;
        }

        statusDiv.textContent = "Uploading image, please wait...";

        const reader = new FileReader();

        reader.onload = function(e) {
          const dataUrl = e.target.result;
          console.log("Data URL:", dataUrl);

          if (dataUrl) {
            google.script.run.withSuccessHandler(function(response) {
              document.getElementById('result').textContent = JSON.stringify(response, null, 2);            
            }).uploadImageToServer(dataUrl);

            statusDiv.textContent = "Image uploaded successfully. Processing...";
          } else {
            console.error("Failed to generate Data URL.");
            statusDiv.textContent = "Error uploading image.";
          }
        };

        reader.onerror = function(error) {
          console.error("Error reading file:", error);
          statusDiv.textContent = "Error uploading image.";
        };

        reader.readAsDataURL(file);
    </script>
  </body>
</html>

I put a console.log and Data URL exists but it is somehow not pass to my GAS function uploadImageToServer().

Here is my Code.gs script

function doGet() {
  return HtmlService.createHtmlOutputFromFile('Index');
}

function uploadImageToServer(dataUrl) {
  Logger.log("Upload function started");

  try {
    Logger.log("Received dataUrl: " + dataUrl);

    if (!dataUrl) {
      throw new Error("No dataUrl received");
    }

    const matches = dataUrl.match(/^data:(.+);base64,(.*)$/);
    if (!matches || matches.length !== 3) {
      throw new Error('Could not parse the data URL.');
    }

    const contentType = matches[1];
    const data = matches[2];
    const blob = Utilities.newBlob(Utilities.base64Decode(data), contentType, "uploaded_image");

    const folder = DriveApp.getFolderById('xxx');
    const file = folder.createFile(blob);
    Logger.log("Image uploaded to Google Drive");

    const imageUrl = file.getUrl();
    Logger.log("Image URL: " + imageUrl);

    // Call Google Cloud Vision API
    const apiKey = 'xxx';
    const visionUrl = `https://vision.googleapis.com/v1/images:annotate?key=${apiKey}`;
    const image = UrlFetchApp.fetch(imageUrl).getBlob().getBytes();
    const encodedImage = Utilities.base64Encode(image);
    Logger.log("Encoded image for Vision API");

    const visionPayload = {
      requests: [
        {
          image: {
            content: encodedImage
          },
          features: [
            {
              type: "TEXT_DETECTION"
            }
          ]
        }
      ]
    };

    const visionOptions = {
      method: "post",
      contentType: "application/json",
      payload: JSON.stringify(visionPayload)
    };

    const visionResponse = UrlFetchApp.fetch(visionUrl, visionOptions);
    Logger.log("Vision API response received");

    const visionData = JSON.parse(visionResponse.getContentText());
    Logger.log("Vision API data parsed: " + JSON.stringify(visionData));

    if (!visionData.responses || !visionData.responses[0] || !visionData.responses[0].fullTextAnnotation) {
      throw new Error("No text found by Vision API");
    }

    const text = visionData.responses[0].fullTextAnnotation.text;
    Logger.log("Extracted text: " + text);

    // Call OpenAI API
    const openaiApiKey = 'xxx';
    const openaiUrl = 'https://api.openai.com/v1/engines/davinci/completions';
    const prompt = `Extract the information from this business card text:nn${text}nnThe information should be in JSON format with keys 'Company', 'Name', 'Title', 'Phone', 'Website', 'Email', and 'Address'.`;

    const openaiPayload = {
      prompt: prompt,
      max_tokens: 150,
      n: 1,
      stop: null,
      temperature: 0.5
    };

    const openaiOptions = {
      method: 'post',
      contentType: 'application/json',
      headers: {
        'Authorization': `Bearer ${openaiApiKey}`
      },
      payload: JSON.stringify(openaiPayload)
    };

    const openaiResponse = UrlFetchApp.fetch(openaiUrl, openaiOptions);
    Logger.log("OpenAI API response received");

    const openaiData = JSON.parse(openaiResponse.getContentText());
    Logger.log("OpenAI API data parsed: " + JSON.stringify(openaiData));

    const jsonResponse = openaiData.choices[0].text.trim();
    Logger.log("OpenAI response parsed: " + jsonResponse);

    const parsedData = JSON.parse(jsonResponse);

    if (!parsedData.Company || !parsedData.Name) {
      throw new Error("Parsed data incomplete");
    }
    
    const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
    const row = [parsedData.Company, parsedData.Name, parsedData.Title, parsedData.Phone, parsedData.Website, parsedData.Email, parsedData.Address];
    sheet.appendRow(row);
    Logger.log("Data appended to Google Sheet");

    return parsedData;
  } catch (error) {
    Logger.log("Error: " + error.message);
    throw error;
  }
}

Here is the Execution Log when I run this code

12:37:37 AM Notice Execution started
12:37:06 AM Info Upload function started
12:37:06 AM Info Received dataUrl: undefined
12:37:06 AM Info Error: No dataUrl received
12:37:37 AM Error

Error: No dataUrl received
uploadImageToServer @ Code.gs:12