An interoperable multipart form field structure for GraphQL requests, used by various file upload client/server implementations.
It’s possible to implement:
variables
).An “operations object” is an Apollo GraphQL POST request (or array of requests if batching). An “operations path” is an object-path
string to locate a file within an operations object.
So operations can be resolved while the files are still uploading, the fields are ordered:
operations
: A JSON encoded operations object with files replaced with null
.map
: A JSON encoded map of where files occurred in the operations. For each file, the key is the file multipart form field name and the value is an array of operations paths.{
query: `
mutation($file: Upload!) {
singleUpload(file: $file) {
id
}
}
`,
variables: {
file: File // a.txt
}
}
curl localhost:3001/graphql \
-F operations='{ "query": "mutation ($file: Upload!) { singleUpload(file: $file) { id } }", "variables": { "file": null } }' \
-F map='{ "0": ["variables.file"] }' \
-F 0=@a.txt
--------------------------cec8e8123c05ba25
Content-Disposition: form-data; name="operations"
{ "query": "mutation ($file: Upload!) { singleUpload(file: $file) { id } }", "variables": { "file": null } }
--------------------------cec8e8123c05ba25
Content-Disposition: form-data; name="map"
{ "0": ["variables.file"] }
--------------------------cec8e8123c05ba25
Content-Disposition: form-data; name="0"; filename="a.txt"
Content-Type: text/plain
Alpha file content.
--------------------------cec8e8123c05ba25--
{
query: `
mutation($files: [Upload!]!) {
multipleUpload(files: $files) {
id
}
}
`,
variables: {
files: [
File, // b.txt
File // c.txt
]
}
}
curl localhost:3001/graphql \
-F operations='{ "query": "mutation($files: [Upload!]!) { multipleUpload(files: $files) { id } }", "variables": { "files": [null, null] } }' \
-F map='{ "0": ["variables.files.0"], "1": ["variables.files.1"] }' \
-F 0=@b.txt \
-F 1=@c.txt
--------------------------ec62457de6331cad
Content-Disposition: form-data; name="operations"
{ "query": "mutation($files: [Upload!]!) { multipleUpload(files: $files) { id } }", "variables": { "files": [null, null] } }
--------------------------ec62457de6331cad
Content-Disposition: form-data; name="map"
{ "0": ["variables.files.0"], "1": ["variables.files.1"] }
--------------------------ec62457de6331cad
Content-Disposition: form-data; name="0"; filename="b.txt"
Content-Type: text/plain
Bravo file content.
--------------------------ec62457de6331cad
Content-Disposition: form-data; name="1"; filename="c.txt"
Content-Type: text/plain
Charlie file content.
--------------------------ec62457de6331cad--
;[
{
query: `
mutation($file: Upload!) {
singleUpload(file: $file) {
id
}
}
`,
variables: {
file: File // a.txt
}
},
{
query: `
mutation($files: [Upload!]!) {
multipleUpload(files: $files) {
id
}
}
`,
variables: {
files: [
File, // b.txt
File // c.txt
]
}
}
]
curl localhost:3001/graphql \
-F operations='[{ "query": "mutation ($file: Upload!) { singleUpload(file: $file) { id } }", "variables": { "file": null } }, { "query": "mutation($files: [Upload!]!) { multipleUpload(files: $files) { id } }", "variables": { "files": [null, null] } }]' \
-F map='{ "0": ["0.variables.file"], "1": ["1.variables.files.0"], "2": ["1.variables.files.1"] }' \
-F 0=@a.txt \
-F 1=@b.txt \
-F 2=@c.txt
--------------------------627436eaefdbc285
Content-Disposition: form-data; name="operations"
[{ "query": "mutation ($file: Upload!) { singleUpload(file: $file) { id } }", "variables": { "file": null } }, { "query": "mutation($files: [Upload!]!) { multipleUpload(files: $files) { id } }", "variables": { "files": [null, null] } }]
--------------------------627436eaefdbc285
Content-Disposition: form-data; name="map"
{ "0": ["0.variables.file"], "1": ["1.variables.files.0"], "2": ["1.variables.files.1"] }
--------------------------627436eaefdbc285
Content-Disposition: form-data; name="0"; filename="a.txt"
Content-Type: text/plain
Alpha file content.
--------------------------627436eaefdbc285
Content-Disposition: form-data; name="1"; filename="b.txt"
Content-Type: text/plain
Bravo file content.
--------------------------627436eaefdbc285
Content-Disposition: form-data; name="2"; filename="c.txt"
Content-Type: text/plain
Charlie file content.
--------------------------627436eaefdbc285--
Pull requests adding either experimental or mature implementations to these lists are welcome!
Strikethrough
means the project was renamed, deprecated, or no longer supports this spec out of the box (but might via an optional integration).
graphql-request Minimal GraphQL client supporting Node and browsers for scripts or simple apps Features Install Quickstart Usage Node Version Support Community GraphQL Code Generator's GraphQL-Request
我正在开发一个基于Spring 3.2.4的小型RESTful服务,并按照本文编写一个自定义函数来发送Multipart请求。 首先,在控制器中,我编写了示例函数进行测试 User对象包含使用Jackson JSON获取和解析数据的用户信息。我还使用cURL发送请求和我测试的命令 这是文本。txt文件 应用程序返回“成功创建!”并记录用户名。它工作正常。 其次,我以为一切都会很简单,但我错了。当我
原因是from标签内未添加enctype="multipart/form-data",因为在表单中的默认情况,这个编码格式是application/x-www-form-urlencoded,不能用于文件上传;只有使用了multipart/form-data,才能完整的传递文件数据。 这里我们需要知道一点,spring在处理入参的时候, 遇到MultipartFile相关就会先去校验。(在controller中会用MultipartFile接受参数)
以下是多部分的子类型 - alternative appledouble byteranges digest encrypted form-data header-set mixed parallel related report signed voice-messagerelated &nsbp; &nsbp;
import "mime/multipart" multipart实现了MIME的multipart解析,参见RFC 2046。该实现适用于HTTP(RFC 2388)和常见浏览器生成的multipart主体。 type File type FileHeader func (fh *FileHeader) Open() (File, error) type Part func (p *Part)
问题内容: 我有一个AJAX请求,可以发送一些数据。数据符合multipart / form-data 规范。 我面临的问题是浏览器将Content-Type标头设置为text / plain,它应该是multipart / form-data。 我尝试这样做:但这会发出400错误的请求错误。 如果我没有错误,则设置“ Content-Typexxxx”标头,但显然对我没有帮助。 我猜这里有一个可