NodeJS 使用 GQL 创建和 POST 文件
NodeJS create and POST file with GQL
我一直无法弄清楚在 NodeJS 中如何:
- 从原始字符串在内存中创建一个“文件”;并且,
- 如何 POST 将数据发送到另一个需要 multipart/form-data 负载的服务器。
似乎您不能在 NodeJS 中使用 Blob
或 File
classes。
我读过的模式应该是使用Buffer
class。
我仍然无法让它与缓冲区一起工作。
我的 GQL 数据源 class 看起来像:
const { RESTDataSource } = require('apollo-datasource-rest');
const FormData = require('form-data');
export default class MyDatasource extends RESTDataSource {
async postFileToServer({ string }) {
const inMemoryFile = Buffer.from(string, 'utf-8');
const myForm = new FormData();
myForm.append('file', inMemoryFile, 'file.txt');
const url = 'http://examnple.com';
const opts = { headers: { 'Content-Type': 'multipart/form-data' } };
return await this.post(url, myForm, opts);
}
}
当我使用 Postman 使用来自本地计算机的文件进行 API 调用时,我想要访问的端点工作正常。但是,我需要 GQL 服务器从原始字符串创建文件,然后调用需要 multipart/form-data.
的 example.com 端点
上面的示例代码总是给我一个Status 400
和SyntaxError: Unexpected token - in JSON at position 0
的错误
我使用 apollo-datasource-rest
包上传文件。这是一个例子:
server.ts
:
import { ApolloServer, gql } from 'apollo-server';
import MyDatasource from './datasource';
const typeDefs = gql`
type Query {
dummy: String
}
type Mutation {
upload: String
}
`;
const resolvers = {
Mutation: {
upload(_, __, { dataSources }) {
return dataSources.uploadAPI.postFileToServer({ str: '1234' });
},
},
};
const server = new ApolloServer({
typeDefs,
resolvers,
dataSources: () => {
return {
uploadAPI: new MyDatasource(),
};
},
});
const port = 3001;
server.listen(port).then(({ url }) => console.log(` Server ready at ${url}`));
datasource.ts
:
import { RESTDataSource } from 'apollo-datasource-rest';
import FormData from 'form-data';
export default class MyDatasource extends RESTDataSource {
public async postFileToServer({ str }) {
const inMemoryFile = Buffer.from(str, 'utf-8');
const myForm = new FormData();
myForm.append('file', inMemoryFile, 'file.txt');
const url = 'http://localhost:3000/upload';
return this.post(url, myForm);
}
}
uploadServer.ts
:
import multer from 'multer';
import express from 'express';
import path from 'path';
const upload = multer({ dest: path.resolve(__dirname, 'uploads/') });
const app = express();
const port = 3000;
app.post('/upload', upload.single('file'), (req, res) => {
console.log(req.file);
console.log(req.body);
res.sendStatus(200);
});
app.listen(port, () => {
console.log(`upload server is listening on http://localhost:${port}`);
});
/upload
API控制器打印的日志:
{
fieldname: 'file',
originalname: 'file.txt',
encoding: '7bit',
mimetype: 'text/plain',
destination: '/Users/ldu020/workspace/github.com/mrdulin/apollo-graphql-tutorial/src/Whosebug/63181608/uploads',
filename: '3cba4dded6089479ad495e2fb2daac21',
path: '/Users/ldu020/workspace/github.com/mrdulin/apollo-graphql-tutorial/src/Whosebug/63181608/uploads/3cba4dded6089479ad495e2fb2daac21',
size: 4
}
[Object: null prototype] {}
源代码:https://github.com/mrdulin/apollo-graphql-tutorial/tree/master/src/Whosebug/63181608
我一直无法弄清楚在 NodeJS 中如何:
- 从原始字符串在内存中创建一个“文件”;并且,
- 如何 POST 将数据发送到另一个需要 multipart/form-data 负载的服务器。
似乎您不能在 NodeJS 中使用 Blob
或 File
classes。
我读过的模式应该是使用Buffer
class。
我仍然无法让它与缓冲区一起工作。
我的 GQL 数据源 class 看起来像:
const { RESTDataSource } = require('apollo-datasource-rest');
const FormData = require('form-data');
export default class MyDatasource extends RESTDataSource {
async postFileToServer({ string }) {
const inMemoryFile = Buffer.from(string, 'utf-8');
const myForm = new FormData();
myForm.append('file', inMemoryFile, 'file.txt');
const url = 'http://examnple.com';
const opts = { headers: { 'Content-Type': 'multipart/form-data' } };
return await this.post(url, myForm, opts);
}
}
当我使用 Postman 使用来自本地计算机的文件进行 API 调用时,我想要访问的端点工作正常。但是,我需要 GQL 服务器从原始字符串创建文件,然后调用需要 multipart/form-data.
的 example.com 端点上面的示例代码总是给我一个Status 400
和SyntaxError: Unexpected token - in JSON at position 0
我使用 apollo-datasource-rest
包上传文件。这是一个例子:
server.ts
:
import { ApolloServer, gql } from 'apollo-server';
import MyDatasource from './datasource';
const typeDefs = gql`
type Query {
dummy: String
}
type Mutation {
upload: String
}
`;
const resolvers = {
Mutation: {
upload(_, __, { dataSources }) {
return dataSources.uploadAPI.postFileToServer({ str: '1234' });
},
},
};
const server = new ApolloServer({
typeDefs,
resolvers,
dataSources: () => {
return {
uploadAPI: new MyDatasource(),
};
},
});
const port = 3001;
server.listen(port).then(({ url }) => console.log(` Server ready at ${url}`));
datasource.ts
:
import { RESTDataSource } from 'apollo-datasource-rest';
import FormData from 'form-data';
export default class MyDatasource extends RESTDataSource {
public async postFileToServer({ str }) {
const inMemoryFile = Buffer.from(str, 'utf-8');
const myForm = new FormData();
myForm.append('file', inMemoryFile, 'file.txt');
const url = 'http://localhost:3000/upload';
return this.post(url, myForm);
}
}
uploadServer.ts
:
import multer from 'multer';
import express from 'express';
import path from 'path';
const upload = multer({ dest: path.resolve(__dirname, 'uploads/') });
const app = express();
const port = 3000;
app.post('/upload', upload.single('file'), (req, res) => {
console.log(req.file);
console.log(req.body);
res.sendStatus(200);
});
app.listen(port, () => {
console.log(`upload server is listening on http://localhost:${port}`);
});
/upload
API控制器打印的日志:
{
fieldname: 'file',
originalname: 'file.txt',
encoding: '7bit',
mimetype: 'text/plain',
destination: '/Users/ldu020/workspace/github.com/mrdulin/apollo-graphql-tutorial/src/Whosebug/63181608/uploads',
filename: '3cba4dded6089479ad495e2fb2daac21',
path: '/Users/ldu020/workspace/github.com/mrdulin/apollo-graphql-tutorial/src/Whosebug/63181608/uploads/3cba4dded6089479ad495e2fb2daac21',
size: 4
}
[Object: null prototype] {}
源代码:https://github.com/mrdulin/apollo-graphql-tutorial/tree/master/src/Whosebug/63181608