0

I am building an Angular App around OPENAI APIs and I have trouble with their Upload function.

The Endpoint is called "files" and the documentation can be found here

It works well when I perform the request from my computer using postman passing a local file.

However in my angular app, the file is located and accessible on the web server and I am trying to post that file to the endpoint and I keep getting an error from the web server : 400 OK "file is a required parameter".

I have tried calling the API by passing the file's URL as the 'file' parameter but that obviously failed.

Now I retrieve the content of the file through an http GET, and have the content as a String in my app.

I have then implemented the following method on my service to send the String as a Blob using formdata :

UploadFile(token: string, file: string): Observable<TrainingFiles> {
    let fileblob = new Blob([file], {
      type: 'text/plain; charset=utf8',
    });

    let body = new FormData();

    body.append('purpose', 'fine-tune');
    body.append('file', fileblob, 'myTrainingFile.jsonl');

    let httpOptions = {
      headers: new HttpHeaders({
        'Content-Type': 'multipart/form-data',
        Authorization: 'Bearer ' + token,
      }),
    };

    return this.http.post<TrainingFiles>(
      'https://api.openai.com/v1/files',
      body,
      httpOptions
    );
  }

he request payload now looks exactly the same than the one send from postman, however I keep getting the same error from the web server :

{ "error": { "message": "'file' is a required property", "type": "invalid_request_error", "param": null, "code": null } }

this is the payload of the SUCCESSFUL request sent by Postman :

POST /v1/files HTTP/1.1
Host: api.openai.com
Authorization: Bearer <my token>
Content-Length: 297
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW

----WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="purpose"

fine-tune
----WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="file"; filename="training_data.jsonl"
Content-Type: <Content-Type header here>

(data)
----WebKitFormBoundary7MA4YWxkTrZu0gW

and here is the FAILED payload sent by my browser when using the app :

------WebKitFormBoundaryJAv06rE853d4kdXC
Content-Disposition: form-data; name="purpose"

fine-tune
------WebKitFormBoundaryJAv06rE853d4kdXC
Content-Disposition: form-data; name="file"; filename="myTrainingFile.jsonl"
Content-Type: text/plain; charset=utf8

<here is the string as a JSONLINE formatted as a series of "{property: value}\n" >

------WebKitFormBoundaryJAv06rE853d4kdXC--

I guess the idea would be to send binary stream rather than the content of the string but I supposed that was what sending a Blob instead of the String was for...

I have tried several other "content type" headers such as "application/jsonline" whithout success.

Thank you all for your attention.

1 Answers1

1

Removing the 'content type' header solved the issue...

Here is a working implementation :

UploadFile(token: string, file: string): Observable<TrainingFiles> {
    let fileblob = new Blob([file], {
      type: 'text/plain; charset=utf8',
    });

    let body = new FormData();

    body.append('purpose', 'fine-tune');
    body.append('file', fileblob, 'myTrainingFile.jsonl');

    let httpOptions = {
      headers: new HttpHeaders({
        Authorization: 'Bearer ' + token,
      }),
    };

    return this.http.post<TrainingFiles>(
      'https://api.openai.com/v1/files',
      body,
      httpOptions
    );
  }