> For the complete documentation index, see [llms.txt](https://ferris-yang.gitbook.io/netflix-dgs-guide-chinese/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://ferris-yang.gitbook.io/netflix-dgs-guide-chinese/advanced/file-uploads.md).

# 文件上传

在 GraphQL 中，你可以模拟一个文件上传操作，作为一个从客户端到 DGS 的 GraphQL mutation request。

下面的场景，描述了你如何使用一个 Multipart POST request 实现文件的上传和下载。对于文件上传和最佳实践的更多信息，请看来自 Apollo 博客 Khalil Stemmler 撰写的 [Apollo Server File Upload Best Practices](https://www.apollographql.com/blog/apollo-server-file-upload-best-practices-1e7f24cdc050)

## Multipart File Upload

一个 multipart request 就是一个带有 multiple parts 的 HTTP 请求：mutation 请求，文件数据，JSON 对象和其他。你可以使用 Apollo 的 Upload 客户端，或者甚至一个简单的 cURL，使用一个你在你的 schema 中，作为一个 Mutation 模拟的 multipart request 来发送一个文件数据的流。

![file-upload-multipart](/files/-M_UgeUoRRXMei5A5-xI)

使用 GraphQL mutations 用于上传文件的 multipart `POST` 请求更多的参数，请参照 [GraphQL multipart request specification](https://github.com/jaydenseric/graphql-multipart-request-spec) 。

DGS 框架支持 `Upload` scalar，在你的 mutation query 中作为一个 `MultipartFile` 来指定。当你发送文件上传的 multipart request 时，框架将处理每个部分并组装最终的GraphQL查询，并将其交给 data fetcher 进行进一步处理。

下面是一个将文件上传到 DGS 的 Mutation 查询示例：

```scheme
scalar Upload

extend type Mutation  {
    uploadScriptWithMultipartPOST(input: Upload!): Boolean
}
```

注意，你需要在你的 Schema 中声明 `Upload` scalar，尽管实现是由 DGS 框架提供的。在你的 DGS 里，添加一个 datafetcher 去处理这个 `MultipartFile`，如下所示：

```java
@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：

```kotlin
import { createUploadLink } from 'apollo-upload-client'

const uploadLink = createUploadLink({ uri: uri })

const authedClient = authLink && new ApolloClient({
        link: uploadLink)),
        cache: new InMemoryCache()
})
```

一旦你设置好，创建你的 Mutation query 并且作为一个变量发送用户选择的文件：

```kotlin
// 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>
  );
}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://ferris-yang.gitbook.io/netflix-dgs-guide-chinese/advanced/file-uploads.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
