如何使用 nestjs-graphql-fastify 服务器上传文件以及如何测试此类功能?
Posted
技术标签:
【中文标题】如何使用 nestjs-graphql-fastify 服务器上传文件以及如何测试此类功能?【英文标题】:How to upload file using nestjs-graphql-fastify server and how to test such feature? 【发布时间】:2022-01-17 06:10:00 【问题描述】:我很难将 .csv 文件上传到 nestjs-graphql-fastify 服务器。尝试以下代码:
@Mutation(() => Boolean)
async createUsers(
@Args( name: 'file', type: () => GraphQLUpload )
createReadStream, filename : FileUpload,
): Promise<boolean>
try
// backend logic . . .
catch
return false;
return true;
但我在使用邮递员进行测试时得到的只是这个响应:
"statusCode": 415,
"code": "FST_ERR_CTP_INVALID_MEDIA_TYPE",
"error": "Unsupported Media Type",
"message": "Unsupported Media Type: multipart/form-data; boundary=--------------------------511769018912715357993837"
使用代码优先的方法进行开发。
更新:尝试使用 fastify-multipart 但问题仍然存在。改变的是邮递员的响应:
POST body missing, invalid Content-Type, or JSON object has no keys.
【问题讨论】:
【参考方案1】:在 Nestjs discord 频道上找到了一些答案。
您必须进行以下更改:
main.ts
async function bootstrap()
const adapter = new FastifyAdapter();
const fastify = adapter.getInstance();
fastify.addContentTypeParser('multipart', (request, done) =>
request.isMultipart = true;
done();
);
fastify.addHook('preValidation', async function (request: any, reply)
if (!request.raw.isMultipart)
return;
request.body = await processRequest(request.raw, reply.raw);
);
const app = await NestFactory.create<NestFastifyApplication>(
AppModule,
adapter,
);
await app.listen(apiServerPort, apiServerHost);
bootstrap();
上传.scalar.ts
import Scalar from '@nestjs/graphql';
import GraphQLUpload from 'graphql-upload';
@Scalar('Upload')
export class UploadGraphQLScalar
protected parseValue(value)
return GraphQLUpload.parseValue(value);
protected serialize(value)
return GraphQLUpload.serialize(value);
protected parseLiteral(ast)
return GraphQLUpload.parseLiteral(ast, ast.value);
users.resolver.ts
@Mutation(() => CreateUsersOutput, name: 'createUsers')
async createUsers(
@Args('input', new ValidationPipe()) input: CreateUsersInput,
@ReqUser() reqUser: RequestUser,
): Promise<CreateUsersOutput>
return this.usersService.createUsers(input, reqUser);
创建-shared.input.ts
@InputType()
export class DataObject
@Field(() => UploadGraphQLScalar)
@Exclude()
public readonly csv?: Promise<FileUpload>;
@InputType()
@ArgsType()
export class CreateUsersInput
@Field(() => DataObject)
public readonly data: DataObject;
另外,我想提一下,你不应该使用全局验证管道(在我的例子中,它们使文件不可读)
// app.useGlobalPipes(new ValidationPipe( transform: true ));
【讨论】:
【参考方案2】:您可以使用graphql-python/gql 尝试上传文件:
from gql import Client, gql
from gql.transport.aiohttp import AIOHTTPTransport
transport = AIOHTTPTransport(url='YOUR_URL')
client = Client(transport=transport)
query = gql('''
mutation($file: Upload!)
createUsers(file: $file)
''')
with open("YOUR_FILE_PATH", "rb") as f:
params = "file": f
result = client.execute(
query, variable_values=params, upload_files=True
)
print(result)
如果你activate logging,你可以看到客户端和后端之间交换了一些消息。
【讨论】:
感谢您的回答,但我必须坚持使用 Nestjs,因此切换到 python 不是很有帮助 rn 嘿,客户端可以是Python,后端是js。如果它适用于 Python,您可以使用日志记录来查看发送的确切内容,然后与邮递员发送的数据进行比较以上是关于如何使用 nestjs-graphql-fastify 服务器上传文件以及如何测试此类功能?的主要内容,如果未能解决你的问题,请参考以下文章
如何在自动布局中使用约束标识符以及如何使用标识符更改约束? [迅速]
如何使用 AngularJS 的 ng-model 创建一个数组以及如何使用 jquery 提交?