Open usersina opened 1 year ago
We have the exact same issue and it's a blocker at the moment. Were you able to omit this issue?
In our .NET backend we have this endpoint:
Upload([FromForm] IFormFile file)
Which creates an open API like this:
requestBody:
content:
multipart/form-data:
Orval generates this:
uploadFile<TData = xxxResponseDto | ProblemDetailsDto>(
postFileBody: PostFileBodyOne | PostFileBodyTwo, options?: HttpClientOptions
): Observable<TData> {
return this.http.post<TData>(
`/upload/validate`,
postFileBody,options
);
}
};
But it should generate this:
uploadFile<TData = xxxResponseDto | ProblemDetailsDto>(
postFileBody: FormData,
options?: HttpClientOptions
): Observable<TData> {
return this.http.post<TData>(`/upload/validate`, postFileBody, options);
}
Than we would be able use this code in the frontend to upload the file:
uploadFile(file: File): Observable<void | xxxResponseDto | ProblemDetailsDto> {
const formData: FormData = new FormData();
formData.append('myFile', file, file.name);
return this.service.postFile(formData);
}
Howerver, with the current implementation in Orval, I would have to create this code in the frontend, the code is a lot more verbose and there is also an issue with the Boundary header which makes this call invalid:
const postFileBody: PostFileBodyOne = {
ContentType: 'application/pdf',
ContentDisposition: 'attachment',
Length: file.size,
Name: 'file',
FileName: file.name,
};
return this.service
.postFile(postFileBody, {
headers: {
'Content-Type': 'multipart/form-data',
'Boundary': <-- calculate valued, eg: --------------------------e8c5c0c3e9f5c5a0
},
})
);
I use a workaround of setting the frontend input to a Blob
, hence removing any validation there. I do make sure to validate backend wise though:
Having the following schema:
{
...
"requestBody": {
"content": {
"multipart/form-data": {
"schema": {
"required": ["files", "projectFileRequest"],
"type": "object",
"properties": {
"projectFileRequest": {
"type": "string",
"description": "Request part containing the file metadata (Temporarily set to a BLOB until parsing issue is fixed. Server validation works though)",
"format": "binary"
},
"files": {
"type": "array",
"items": {
"type": "string",
"format": "binary"
}
}
}
}
}
}
}
...
}
I then proceed to call it like so, in a react app:
const uploadFilesMutation = useUploadPacketFiles();
const handleUpload = (newFiles: File[]) => {
uploadFilesMutation.mutate(
{
data: {
files: newFiles,
projectFileRequest: new Blob(
[
JSON.stringify({
projectId: "project.id",
creatorId: "user.id",
}),
],
{ type: "application/json" },
),
},
},
{
onSuccess(results) {
console.log("Uploaded file ids", results);
},
},
);
};
Things get interesting when I take a look the Opeqsdfn API that is being generated. If you take a look at the specifications by Swagger
requestBody:
content:
image/png:
schema:
type: string
format: binary
then Orval is able to correctly generate it.
So I guess I must find a way to make my .NET backend spit this out, instead of some nonesence 😅
I had the same problem and I fixed it by doing this:
orval.config.ts
:
import { defineConfig } from 'orval';
export default defineConfig({
cresoPlus: {
input: {
target: './docs/api.yaml',
},
output: {
clean: true,
client: 'react-query',
mock: false,
mode: 'tags',
override: {
formData: {
name: 'customFormDataFn',
path: './src/api/overrides/formData.ts',
},
mutator: {
name: 'customAxiosInstance',
path: './src/lib/axios.ts',
},
},
packageJson: './package.json',
prettier: true,
schemas: './src/api/generated/models',
target: './src/api/generated',
tsconfig: './tsconfig.json',
},
},
});
./src/api/overrides/formData.ts
:
export const customFormDataFn = <Body extends object>(body: Body): FormData => {
const formData = new FormData();
Object.entries(body).forEach(([key, value]) => {
if (value !== undefined && value !== null) {
if (value instanceof Blob) {
formData.append(key, value);
} else {
formData.append(
key,
new Blob([JSON.stringify(value)], {
type: 'application/json',
}),
);
}
}
});
return formData;
};
What are the steps to reproduce this issue?
Given the following schema, generate the
client
typesWhat happens?
For the upload function using
client: "react-query"
, this is what's generatedHowever, this is broken and will result in the following error
The reason for this, is that the
personDTO
field is expected to be encoded inapplication/json
and not in the defaultapplication/octet-stream
.What were you expecting to happen?
Instead, this is what works if I manually update the file
Any other comments?
This issue is very closely related.
What versions are you using?
Package Version:
^6.15.0