iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 19
0
Data Technology

GraphQL + ApolloData 入門系列 第 19

ApolloGraphql & Upload套件 ServerPart(三)

介紹

前兩篇介紹了 ServerPart 的內容 ,套用在實際開發上步驟如下

步驟一 在 graphql endpoint 加入,順便加上設定config 檔案
import { apolloUploadKoa } from 'apollo-upload-server'或
import { apolloUploadExpress } from 'apollo-upload-server'

https://ithelp.ithome.com.tw/upload/images/20171225/20103438VdWWA9cXj9.png

步驟二 定義 Upload resolver

import { makeExecutableSchema } from 'graphql-tools'
import { GraphQLUpload } from 'apollo-upload-server'
 
const schema = makeExecutableSchema({
  typeDefs: [`scalar Upload`],
  resolvers: {
    Upload: GraphQLUpload
  }
})

步驟三 寫resolvers 原本很複雜的 upload 只需要定義好可以直接用apollo-upload-server提供的 processRequest 直接用就可以了

這邊要記得使用 scalar Upload 這樣在input那邊才可以使用Upload這個擴展的型別

在resolver這邊把接到的upload 先把檔案資訊抽離出來在存成檔案並記錄到StoreDB

const processUpload = async upload => {
  const { stream, filename, mimetype, encoding } = await upload
  const { id2, path } = await storeFS({ stream, filename })
  return storeDB({ id2, filename, mimetype, encoding, path })
}
import fs from 'fs'
import promisesAll from 'promises-all'
import mkdirp from 'mkdirp'
import shortid from 'shortid'
import lowdb from 'lowdb'
import FileSync from 'lowdb/adapters/FileSync'
import { GraphQLUpload } from 'apollo-upload-server'

const uploadDir = './uploads'
const db = lowdb(new FileSync('db.json'))

// Seed an empty DB
db.defaults({ uploads: [] }).write()

// Ensure upload directory exists
mkdirp.sync(uploadDir)

const storeFS = ({ stream, filename }) => {
  const id2 = shortid.generate()
  const path = `${uploadDir}/${id2}-${filename}`
  return new Promise((resolve, reject) =>
    stream
      .on('error', error => {
        if (stream.truncated)
          // Delete the truncated file
          fs.unlinkSync(path)
        reject(error)
      })
      .on('end', () => resolve({ id2, path }))
      .pipe(fs.createWriteStream(path))
  )
}

const storeDB = file =>
  db
    .get('uploads')
    .push(file)
    .last()
    .write()

const processUpload = async upload => {
  const { stream, filename, mimetype, encoding } = await upload
  const { id2, path } = await storeFS({ stream, filename })
  return storeDB({ id2, filename, mimetype, encoding, path })
}

export default {
  Upload: GraphQLUpload,
  Query: {
    uploads: () => db.get('uploads').value()
  },
  Mutation: {
    singleUpload: (obj, { file }) => {
      console.log(obj)
      return processUpload(file)
    },
    multipleUpload: async (obj, { files }) => {
      const { resolve, reject } = await promisesAll.all(
        files.map(processUpload)
      )

      if (reject.length)
        reject.forEach(({ name, message }) =>
          // eslint-disable-next-line no-console
          console.error(`${name}: ${message}`)
        )

      return resolve
    }
  }
}

這個作者也有影片說明的很詳細
https://www.youtube.com/watch?v=V95tULgGpLo

https://github.com/jaydenseric/apollo-upload-server/blob/master/src/index.mjs

總結

ApolloData apollo-upload-server 套件,因為環節較多所以每個步驟設定都要注意參數與定義名稱,這篇先卡一下 processRequest 的部份找時間補

https://www.npmjs.com/package/apollo-upload-server


上一篇
ApolloData & Upload套件 ServerPart(二)
下一篇
ApolloData & Upload套件 ClientPart
系列文
GraphQL + ApolloData 入門30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言