You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SharePoint Online调用IBM Cloud文件上传API遇跨域及请求错误

Solution for Calling IBM Cloud Services from SharePoint Online with File Upload

Let's break down your problem first: you're stuck between two conflicting issues—using SP.WebProxy.invoke fixes SharePoint's CORS problem but fails because the IBM API rejects your JSON-formatted file body; using FormData directly works for IBM but gets blocked by CORS in SharePoint. The fix is to combine the best of both approaches: use SP.WebProxy to handle cross-domain requests, while constructing a proper multipart/form-data request body that IBM's API expects.

Why Your Previous Attempts Failed

  • Attempt 1 Issue: IBM Visual Recognition's API requires files to be sent as multipart/form-data, not JSON. Your code was wrapping the file content in a JSON object, which the API couldn't parse correctly.
  • Attempt 2 Issue: Directly sending an XMLHttpRequest to IBM's domain triggers browser CORS restrictions, since IBM's server doesn't include SharePoint's domain in its CORS allowlist.

Working Solution: Proxy + Proper Multipart Request

We'll use SP.WebProxy to forward the request, and manually construct a valid multipart/form-data body to upload your file to IBM's API. Here's the step-by-step code:

1. Helper Functions to Prepare File Data

First, we need to read the file as a raw buffer and convert it to a string that preserves binary data (using Latin1 encoding, since each byte maps directly to a character):

// Read file as ArrayBuffer and convert to Latin1 string (preserves binary data)
function getFileBuffer(file, callback) {
  const reader = new FileReader();
  reader.readAsArrayBuffer(file);
  reader.onload = () => {
    const buffer = new Uint8Array(reader.result);
    const bufferStr = String.fromCharCode(...buffer);
    callback(bufferStr);
  };
  reader.onerror = (error) => {
    console.error('Error reading file:', error);
  };
}

// Construct valid multipart/form-data body
function constructMultipartBody(fileName, fileBuffer) {
  const boundary = `----WebKitFormBoundary${Math.random().toString(16).slice(2)}`;
  const parts = [
    `--${boundary}`,
    `Content-Disposition: form-data; name="images_file"; filename="${fileName}"`,
    'Content-Type: image/png', // Adjust based on your file type
    '', // Empty line separating headers from content
    fileBuffer,
    `--${boundary}--`,
    ''
  ];
  return {
    boundary: boundary,
    body: parts.join('\r\n')
  };
}

2. Main Function to Call IBM API via SharePoint Proxy

This function uses SP.WebProxy to forward the request, with the properly formatted multipart body:

function uploadToIBMVisualRecognition() {
  const file = document.getElementById('imagem').files[0];
  if (!file) {
    alert('Please select a file first!');
    return;
  }

  getFileBuffer(file, (fileBuffer) => {
    const multipartData = constructMultipartBody(file.name, fileBuffer);
    const ibmApiUrl = 'https://gateway-a.watsonplatform.net/visual-recognition/api/v3/classify?api_key={YOUR-API-KEY}&version=2016-05-20';

    $.ajax({
      url: '../_api/SP.WebProxy.invoke',
      type: 'POST',
      data: JSON.stringify({
        requestInfo: {
          '__metadata': { type: 'SP.WebRequestInfo' },
          Url: ibmApiUrl,
          Method: 'POST',
          Headers: {
            results: [
              {
                '__metadata': { type: 'SP.KeyValue' },
                Key: 'Accept',
                Value: 'application/json',
                ValueType: 'Edm.String'
              },
              {
                '__metadata': { type: 'SP.KeyValue' },
                Key: 'Content-Type',
                Value: `multipart/form-data; boundary=${multipartData.boundary}`,
                ValueType: 'Edm.String'
              }
            ]
          },
          Body: multipartData.body
        }
      }),
      headers: {
        'Accept': 'application/json;odata=verbose',
        'Content-Type': 'application/json;odata=verbose',
        'X-RequestDigest': document.getElementById('__REQUESTDIGEST').value
      },
      success: (data) => {
        alert('Success!');
        try {
          const response = JSON.parse(data.d.Invoke.Body);
          console.log('IBM API Response:', response);
        } catch (e) {
          console.log('Raw Response:', data.d.Invoke.Body);
        }
      },
      error: (xhr, status, error) => {
        alert('Request failed. Check console for details.');
        console.error('Error Status:', status);
        console.error('Error Message:', error);
        console.error('Response:', xhr.responseText);
      }
    });
  });
}

Key Notes

  • API Parameter Name: IBM's Visual Recognition API expects the file parameter to be named images_file (not imagemTeste as in your second attempt). Double-check the official docs for any updates.
  • Content-Type Matching: Ensure the Content-Type header's boundary matches the one used in the multipart body. This is critical for the API to parse the request correctly.
  • File Type: Adjust the Content-Type in constructMultipartBody if you're uploading non-PNG files (e.g., image/jpeg for JPGs).
  • Permissions: Make sure the current SharePoint user has permission to use SP.WebProxy—this is enabled by default for most users in SharePoint Online.

内容的提问来源于stack exchange,提问作者David Silva

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:10:56