Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Request falls if FormData attachment is File instance #293

Closed
NooNoo1337 opened this issue Sep 8, 2021 · 3 comments · Fixed by #294
Closed

Request falls if FormData attachment is File instance #293

NooNoo1337 opened this issue Sep 8, 2021 · 3 comments · Fixed by #294
Assignees
Labels
bug Something isn't working

Comments

@NooNoo1337
Copy link

NooNoo1337 commented Sep 8, 2021

Hi! I got issue with file format in FormData request. Library version: 9.0.2.

Next entity is described in OpenApi format:

 FileSegmentCreate:
      type: object
      required:
        - files
      properties:
        files:
          type: array
          items:
            type: string
            format: binary
// Auto generated TS interface
export interface FileSegmentCreate {
    files: File[];
}

When I make request with file it falls because of the incorrect file format. After research I have found the trouble point in generated code, contentFormatters object.

After contentFormatters code review I found out that:

  1. it's not allowed to have multiply files in same FormData key. There is no check for array input type;
  2. there is no check for Blob or File instance.
 // contentFormatters
 [ContentType.FormData]: (input: any) =>
      Object.keys(input || {}).reduce((data, key) => {
        data.append(key, input[key]);
        return data;
      }, new FormData()),

I'm able to resolve the instance issue on my side but It's hack.

//  createFileSegment expects that "files" key has File[] type;
const files = segment.files.map((file) => new Blob([file])) as any;
    
await api.createFileSegment({ ...segment, files: files[0] });

I noticed updates in 9.2.0 lib version that Blob instance check was added. However, the request will fall again if property is File instance or if it's Blob[] or Files[].

return Object.keys(input || {}).reduce((formData, key) => {
        const property = input[key];
        formData.append(
            key,
            property instanceof Blob ?
                property :
            typeof property === "object" && property !== null ?
                JSON.stringify(property) :
            `${property}`
        );
        return formData;
      }, new FormData())

Questions

  • is it able to add code to convert attachment to Blob if attachment has instance File?
  • is it able to add check for detecting few attachments?
@js2me js2me self-assigned this Oct 4, 2021
@js2me js2me linked a pull request Oct 4, 2021 that will close this issue
@js2me js2me added the bug Something isn't working label Oct 4, 2021
@kuamanet
Copy link
Contributor

Sorry to bother, can someone point me at the line in the next branch where this issue gets resolved? I still see

createFormData(input) {
    return Object.keys(input || {}).reduce((formData, key) => {
      const property = input[key];
      formData.append(
        key,
        property instanceof Blob
          ? property
          : typeof property === "object" && property !== null
          ? JSON.stringify(property)
          : `${property}`,
      );
      return formData;
    }, new FormData());
  }

@RoXuS
Copy link

RoXuS commented Jan 20, 2022

same issue here.

If you rewrite the fetch eta it seems ok:

 private contentFormatters: Record<ContentType, (input: any) => any> = {
        [ContentType.Json]: (input:any) => input !== null && (typeof input === "object" || typeof input === "string") ? JSON.stringify(input) : input,
        [ContentType.FormData]: (input: any) =>
           Object.keys(input || {}).reduce((formData, key) => {
            const property = input[key];
            if(Array.isArray(property)) {
                property.forEach((p) => {
                    formData.append(key, p)
                });
            } else {
                formData.append(
                    key,
                    property instanceof Blob
                    ? property
                    : typeof property === 'object' && property !== null
                    ? JSON.stringify(property)
                    : `${property}`
                );
            }
            return formData;
        }, new FormData()),
        [ContentType.UrlEncoded]: (input: any) => this.toQueryString(input),
    }

@Clovel
Copy link

Clovel commented Nov 22, 2022

I noticed updates in 9.2.0 lib version that Blob instance check was added. However, the request will fall again if property is File instance or if it's Blob[] or Files[].

Weird, File seams to be an instanceof Blob (example from Chrome console) :

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants