介紹
前兩篇介紹了 ServerPart 的內容 ,套用在實際開發上步驟如下
步驟一 在 graphql endpoint 加入,順便加上設定config 檔案
import { apolloUploadKoa } from 'apollo-upload-server'或
import { apolloUploadExpress } from 'apollo-upload-server'
步驟二 定義 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