You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

使用Delphi调用REST API发送附件时出现400错误的技术求助

Troubleshooting Delphi REST API Attachment Uploads (400 Bad Request)

Hey there! Let's figure out why your Delphi code is throwing a 400 Bad Request when sending attachments—since Postman works perfectly, the issue is almost certainly in how your request is structured in code. Here are the most likely fixes:

Key Issues to Check

1. You’re Using Raw Body Instead of Multipart Form-Data

Most file upload APIs expect requests to use multipart/form-data format (this is what Postman automatically uses when you add a file). Your current code is sending the file content as a raw body, which doesn’t match what the API expects.

2. Metadata in Headers vs. Form Parameters

You’re sending Filename and edi-document-qualifier as HTTP headers, but it’s far more common for APIs to expect these as form fields alongside the file. Postman might be passing them as form data without you noticing.

3. Unreliable Byte Array Conversion

Your FileToByteArray function uses manual pointer arithmetic, which can cause bugs (especially in 64-bit Delphi). Using TFileStream directly is safer and more maintainable.

Fixed Delphi Code Example

Here’s a revised version of your code that addresses these issues:

begin
  RespID := MyParams.Values['RespID'];
  // Set up the endpoint
  RESTrequest1.Resource := StringReplace(sendAttachments_endPoint, ':messageId', RespID, [rfReplaceAll]);
  RESTrequest1.Method := rmPOST;

  // Clear previous state
  RESTrequest1.Params.Clear;
  RESTrequest1.Body.ClearBody;

  // Reuse your working auth headers
  RESTrequest1.AddAuthParameter('api-key', authAPIkey, pkHTTPHEADER, [poDoNotEncode]);
  RESTrequest1.AddAuthParameter('Authorization', 'Bearer ' + JWToken, pkHTTPHEADER, [poDoNotEncode]);

  NbrOfAttach := StrToInt(MyParams.Values['attachments']);
  for idx := 1 to NbrOfAttach do
  begin
    AttachName := MyParams.Values['attach_' + IntToStr(idx)];
    FileName := ExtractFileName(AttachName);
    
    // Use TFileStream for safe file reading
    var fs := TFileStream.Create(AttachName, fmOpenRead or fmShareDenyWrite);
    try
      // Set the correct content type for multipart uploads
      RESTrequest1.AddParameter('Content-Type', 'multipart/form-data', pkHTTPHEADER, [poDoNotEncode]);

      // Add the file as a form data part (check API docs for the correct field name, e.g., 'file' or 'attachment')
      var fileParam := RESTrequest1.Params.AddItem;
      fileParam.Name := 'file';
      fileParam.Value := FileName;
      fileParam.Kind := pkREQUESTBODY;
      // Set correct content type based on file type
      if LowerCase(ExtractFileExt(AttachName)) = '.pdf' then
        fileParam.ContentType := 'application/pdf'
      else if LowerCase(ExtractFileExt(AttachName)) = '.jpeg' then
        fileParam.ContentType := 'image/jpeg';
      fileParam.SetStream(fs, True); // Let RESTRequest manage stream cleanup

      // Add Filename as a form parameter (not header)
      var fileNameParam := RESTrequest1.Params.AddItem;
      fileNameParam.Name := 'Filename';
      fileNameParam.Value := FileName;
      fileNameParam.Kind := pkREQUESTBODY;
      fileNameParam.Options := [poDoNotEncode];

      // Add edi-document-qualifier as a form parameter (not header)
      var qualifierParam := RESTrequest1.Params.AddItem;
      qualifierParam.Name := 'edi-document-qualifier';
      qualifierParam.Value := IntToStr(idx);
      qualifierParam.Kind := pkREQUESTBODY;
      qualifierParam.Options := [poDoNotEncode];

      try
        RESTrequest1.Execute;
        REST_RepStatus := RESTresponse1.StatusCode;
        if REST_RepStatus = 200 then
          Writeln('Attachment ', idx, ' uploaded successfully!')
        else
          Writeln('Error uploading attachment ', idx, ': ', RESTresponse1.StatusText, ' (Code: ', REST_RepStatus, ')');
      except
        on E: Exception do
          Writeln('Exception uploading attachment ', idx, ': ', E.Message);
      end;
    finally
      fs.Free;
    end;
  end;
end;

Additional Tips for Debugging

  • Compare Requests with Postman: Use a tool like Fiddler or Wireshark to capture the exact request Postman sends, then compare it to what your Delphi code sends. Look for differences in headers, form field names, or multipart boundaries.
  • Check API Documentation: Confirm if the API expects specific form field names (e.g., maybe it uses attachment instead of file for the file parameter).
  • Test One Attachment at a Time: Simplify your loop to upload a single attachment first—this makes it easier to isolate issues.

内容的提问来源于stack exchange,提问作者Jean-Philippe

火山引擎 最新活动