文件上传
在 GraphQL 中,你可以模拟一个文件上传操作,作为一个从客户端到 DGS 的 GraphQL mutation request。
下面的场景,描述了你如何使用一个 Multipart POST request 实现文件的上传和下载。对于文件上传和最佳实践的更多信息,请看来自 Apollo 博客 Khalil Stemmler 撰写的 Apollo Server File Upload Best Practices
Multipart File Upload
一个 multipart request 就是一个带有 multiple parts 的 HTTP 请求:mutation 请求,文件数据,JSON 对象和其他。你可以使用 Apollo 的 Upload 客户端,或者甚至一个简单的 cURL,使用一个你在你的 schema 中,作为一个 Mutation 模拟的 multipart request 来发送一个文件数据的流。

使用 GraphQL mutations 用于上传文件的 multipart POST
请求更多的参数,请参照 GraphQL multipart request specification 。
DGS 框架支持 Upload
scalar,在你的 mutation query 中作为一个 MultipartFile
来指定。当你发送文件上传的 multipart request 时,框架将处理每个部分并组装最终的GraphQL查询,并将其交给 data fetcher 进行进一步处理。
下面是一个将文件上传到 DGS 的 Mutation 查询示例:
scalar Upload
extend type Mutation {
uploadScriptWithMultipartPOST(input: Upload!): Boolean
}
注意,你需要在你的 Schema 中声明 Upload
scalar,尽管实现是由 DGS 框架提供的。在你的 DGS 里,添加一个 datafetcher 去处理这个 MultipartFile
,如下所示:
@DgsData(parentType = DgsConstants.MUTATION.TYPE_NAME, field = "uploadScriptWithMultipartPOST")
public boolean uploadScript(DataFetchingEnvironment dfe) throws IOException {
// NOTE: Cannot use @InputArgument or Object Mapper to convert to class, because MultipartFile cannot be
// deserialized
MultipartFile file = dfe.getArgument("input");
String content = new String(file.getBytes());
return ! content.isEmpty();
}
注意你不能使用 Jackson Object Mapper 去反序列化包含了 MultipartFile
的类型,你需要在你的输入中显式的获得文件参数。
在你的客户端,你可以使用 apollo-upload-client
去发送你的作为一个 multipart POST
包含文件数据的 Mutation query。下面是怎样配置你的 link:
import { createUploadLink } from 'apollo-upload-client'
const uploadLink = createUploadLink({ uri: uri })
const authedClient = authLink && new ApolloClient({
link: uploadLink)),
cache: new InMemoryCache()
})
一旦你设置好,创建你的 Mutation query 并且作为一个变量发送用户选择的文件:
// query for file uploads using multipart post
const UploadScriptMultipartMutation_gql = gql`
mutation uploadScriptWithMultipartPOST($input: Upload!) {
uploadScriptWithMultipartPOST(input: $input)
}
`;
function MultipartScriptUpload() {
const [
uploadScriptMultipartMutation,
{
loading: mutationLoading,
error: mutationError,
data: mutationData,
},
] = useMutation(UploadScriptMultipartMutation_gql);
const [scriptMultipartInput, setScriptMultipartInput] = useState<any>();
const onSubmitScriptMultipart = () => {
const fileInput = scriptMultipartInput.files[0];
uploadScriptMultipartMutation({
variables: { input: fileInput },
});
};
return (
<div>
<h3> Upload script using multipart HTTP POST</h3>
<form
onSubmit={e => {
e.preventDefault();
onSubmitScriptMultipart();
}}>
<label>
<input
type="file"
ref={ref => {
setScriptMultipartInput(ref!);
}}
/>
</label>
<br />
<br />
<button type="submit">Submit</button>
</form>
</div>
);
}
最后更新于
这有帮助吗?