前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >GraphQL: File Upload & Troubleshooting

GraphQL: File Upload & Troubleshooting

作者头像
szhshp
发布2022-09-21 10:39:11
3400
发布2022-09-21 10:39:11
举报

GraphQL File Upload

All implementations and extensions are based on graphql-multipart-request-spec

Client

ApolloClient Setup

Client is using apollo-upload-client which implemented graphql-multipart-request-spec

Replace HttpLink with createUploadLink

Those two do the same thing, feel free to replace it!

代码语言:javascript
复制
import {
    ApolloClient,
    InMemoryCache
} from '@apollo/client';
import {
    createUploadLink
} from 'apollo-upload-client';

const client = new ApolloClient(config);

Add Scalar

代码语言:javascript
复制
Upload scalar

Due to different dependencies, this may cause some error, see Troubleshooting below

Add Schema

代码语言:javascript
复制
type Mutation {
    singleUpload(file: Upload!): File!
}

type File {
    filename: String!
    mimetype: String!
    encoding: String!
}

Frontend

Provide an input or use other frontend components to select a file:

代码语言:javascript
复制
<input type="file" onchange={fileUpload}>

Then validate the selected file:

代码语言:javascript
复制
const uploadOnChange = async (files: File[]) => {
    if (files.length === 0) return
    if (files.filter((file) => file.size > 10 * 1024 * 1024).length > 0) {
        /* throw error: file size exceed */
        return
    }
    if (
        files.filter(
            (file) => [ `image/png` , `image/jpeg` ].findIndex(
                (type) => file.type === type
            ) === -1
        ).length > 0
    ) {
        /* throw error: unacceptable file type */
        return
    }

    /* trigger mutation here */
}

Backend

GraphQL port it to assets server

If you are using Javascript, skip the import of graphql-upload If you are using Typescript, you can use graphql-upload for type check, which implemented graphql-multipart-request-spec

代码语言:javascript
复制
import { FileUpload } from "graphql-upload";

const uploadFile = async (filePromise: {
  file: FileUpload;
}): Promise<boolean> => {
  try {
    const { file }: { file: FileUpload } = await filePromise;
    const fileReadStream = file.createReadStream(); // get the file readstream 

    /* ----------------------------- `*/
    /* Option 1: You can save the file on current server */
    /* const writeStream = fs.createWriteStream('fakepath/output.png') */
    /* Convert stream to file */
    /* readStream.pipe(writeStream) */

    /* ----------------------------- */
    /* Option 2: You can port the file to assets server if you need */
    const formData = new FormData();
    formData.append("attachmentData", fileReadStream, file.filename);

    await http.post( `assetsServer/fileUpload` , formData, {
      headers: {
        ...formData.getHeaders(),
      },
      timeout: 30000,
    });
    return true;
  } catch (error) {
    return false;
  }
};

const resolvers = {
  Query: {
    files: () => {
      // Return the record of files uploaded from your DB or API or filesystem.
    }
  },
  Mutation: {
    uploadFile
  },
};

Troubleshooting

There can be only one type named "Upload"

Possibly you included one lib which ALREADY implemented Upload Type, so you just need to delete scalar Upload

Unknown type "Upload". Did you mean "Float"?

You forget to add the scalar Upload

scalar Upload always causes error :(

  • If I add it -> Error: There can be only one type named "Upload"
  • If I remove it -> Error: Unknown type "Upload". Did you mean "Float"? Oh you got some tricky dependencies.

Try use other names like:

代码语言:javascript
复制
scalar FileUpload

That may help your issue, GraphQL may regard it as custom scalar.

createReadStream() crashes-RangeError: Maximum call stack size exceeded

代码语言:javascript
复制
RangeError: Maximum call stack size exceeded
        at _openReadFs (internal/fs/streams.js:1:1) 

This is due to outdated dependency of fs-capacitor .

To prevent future compatibility issue, set resolutions in package.json :

代码语言:javascript
复制
"resolutions": {
  "graphql-upload": "11.0.0"
},

Be aware that resolutions property is currently only handled by yarn package manager, not by npm

with npm, you have to preinstall an aditionnal module to force resolutions :

代码语言:javascript
复制
"scripts": {
  "preinstall": "npx npm-force-resolutions",
}

References

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-10-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • GraphQL File Upload
    • Client
      • ApolloClient Setup
      • Add Scalar
      • Add Schema
      • Frontend
      • Backend
    • Troubleshooting
      • There can be only one type named "Upload"
      • Unknown type "Upload". Did you mean "Float"?
      • scalar Upload always causes error :(
      • createReadStream() crashes-RangeError: Maximum call stack size exceeded
    • References
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档