Kiota TypeScript中MultipartBody报错及TS接口生成问询
问题1:Kiota生成的客户端发送Multipart请求报错
Error: unsupported content type for multipart body: object C# 后端端点代码
app.MapPost("/handle-form", async (HttpRequest request) => { IFormCollection form = await request.ReadFormAsync(); MyForm myForm = new() { Name = form["Name"]!, Comment = form["Comment"], MyFile = form.Files["MyFile"]!, Attachments = [.. form.Files.Where(x => Regex.IsMatch(x.Name, @"^Attachments\[\d+\]$", RegexOptions.IgnoreCase))] }; return Results.Ok(myForm); }) .Accepts<MyForm>("multipart/form-data") .DisableAntiforgery();
TypeScript 客户端相关代码
Kiota生成的post方法
/** * @param body The request body * @param requestConfiguration Configuration for the request such as headers, query parameters, and middleware options. * @returns {Promise<ArrayBuffer>} */ post(body: MultipartBody, requestConfiguration?: RequestConfiguration<object> | undefined) : Promise<ArrayBuffer | undefined>;
客户端调用代码(报错版本)
const handleFormSubmit = async (e: React.FormEvent<HTMLFormElement>) => { e.preventDefault(); const formData = new FormData(e.currentTarget); const name = formData.get("name")?.toString() || ""; const comment = formData.get("comment")?.toString() || ""; const myFile = formData.get("myFile") as File; const attachments = Array.from(formData.getAll("attachments")) as File[]; const multipartBody = new MultipartBody(); multipartBody.addOrReplacePart("Name", "application/text-plain", name); multipartBody.addOrReplacePart("Comment", "application/text-plain", comment); multipartBody.addOrReplacePart("MyFile", "application/octet-stream", myFile); attachments.forEach((file, index) => { multipartBody.addOrReplacePart(`Attachments[${index}]`, "application/octet-stream", file); }); await client.handleForm.post(multipartBody); // Error while sending post: Error: unsupported content type for multipart body: object }
解决方案
报错原因是Kiota的MultipartBody处理文本字段时,需要用Kiota提供的StringContent类型包装原始字符串,而非直接传入字符串。同时要修正标准MIME类型:
import { StringContent } from '@microsoft/kiota-abstractions'; const handleFormSubmit = async (e: React.FormEvent<HTMLFormElement>) => { e.preventDefault(); const formData = new FormData(e.currentTarget); const name = formData.get("name")?.toString() || ""; const comment = formData.get("comment")?.toString() || ""; const myFile = formData.get("myFile") as File; const attachments = Array.from(formData.getAll("attachments")) as File[]; const multipartBody = new MultipartBody(); // 文本字段用StringContent包装,MIME类型修正为标准的text/plain multipartBody.addOrReplacePart("Name", "text/plain", new StringContent(name)); multipartBody.addOrReplacePart("Comment", "text/plain", new StringContent(comment)); // 文件字段直接传入File对象,使用文件自身的MIME类型 multipartBody.addOrReplacePart("MyFile", myFile.type || "application/octet-stream", myFile); attachments.forEach((file, index) => { multipartBody.addOrReplacePart(`Attachments[${index}]`, file.type || "application/octet-stream", file); }); await client.handleForm.post(multipartBody); }
问题2:能否从OpenAPI Schema生成TypeScript接口保证类型安全?
可以,通过Kiota直接生成包含Model类型的客户端代码即可实现:
确保OpenAPI Schema完整定义模型
确认你的OpenAPI规范中已明确MyForm的结构,包括文本字段和文件字段的类型约束。重新生成Kiota客户端
使用Kiota CLI生成客户端时,默认会根据Schema自动生成对应的TypeScript接口。执行以下命令:kiota generate -l typescript -d openapi-spec.json -o ./src/api生成后,输出目录的
models文件夹下会自动生成与C#MyForm类对应的TypeScript接口,示例:export interface MyForm { name?: string; comment?: string; myFile?: File; attachments?: File[]; }使用生成的Model优化代码
直接用生成的接口约束请求参数或响应数据,确保前后端类型一致:import { MyForm } from './api/models/myForm'; // 处理响应时做类型断言 const response = await client.handleForm.post(multipartBody); const result = JSON.parse(new TextDecoder().decode(response)) as MyForm;
这样就能实现C#类与TypeScript类型的双向类型安全,保证类型完整性。
内容的提问来源于stack exchange,提问作者tgo
相关产品推荐
相关产品推荐

