123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 |
- import { IResolvers } from 'apollo-server-express'
- import fs from 'fs'
- import randombytes from 'randombytes'
- import sharp from 'sharp'
- import { tmpDir, uploadDir, thumbnails } from './constants'
- import user from '../user'
- export const resolvers: IResolvers = {
- Query: {
- fsFiles: async (parent, { directory }, context, info) => {
- user.checkPermission(context, 'ADMIN')
- const data = await fsFiles(directory)
- return data
- },
- files: (parent, args, context, info) => {
- user.checkPermission(context, 'ADMIN')
- return context.db.query.files(args, info)
- }
- },
- Mutation: {
- uploadFile: async (parent, { comment, file }, context, info) => {
- user.checkPermission(context, 'ADMIN')
- const fileInfo = await uploadFile(file)
- return context.db.mutation.createFile(
- {
- data: {
- ...fileInfo,
- comment,
- user: { connect: { id: context.req.userId } }
- }
- },
- info
- )
- }
- }
- }
- async function fsFiles(directory: string) {
- const fileList = await fs.promises.readdir(directory)
- return Promise.all(
- fileList.map(async filename => {
- const path = `${directory}/${filename}`
- const { size, ctime, mtime } = await fs.promises.stat(path)
- return {
- filename,
- path,
- size,
- ctime,
- mtime
- }
- })
- )
- }
- async function uploadFile(file: any) {
- const { createReadStream, filename, mimetype, encoding } = await file
- const stream = createReadStream()
- const fsFilename = randombytes(16).toString('hex')
- const tmpPath = `${tmpDir}/${fsFilename}`
- const path = `${uploadDir}/${fsFilename}`
- const thumbnailPath = `${thumbnails}/${fsFilename}`
- await new Promise((resolve, reject) => {
- const file = fs.createWriteStream(tmpPath)
- file.on('finish', resolve)
- file.on('error', error => {
- fs.unlink(tmpPath, () => {
- reject(error)
- })
- })
- stream.on('error', (error: any) => file.destroy(error))
- stream.pipe(file)
- })
- if (mimetype.startsWith('image/')) {
- try {
- await processImage(tmpPath, path)
- await createThumbnail(tmpPath, thumbnailPath)
- await fs.promises.unlink(tmpPath)
- } catch (error) {
- try {
- await fs.promises.unlink(tmpPath)
- await fs.promises.unlink(path)
- } catch (ignore) {}
- throw error
- }
- }
- const { size } = await fs.promises.stat(path)
- return {
- filename,
- path,
- mimetype,
- encoding,
- size
- }
- }
- function processImage(tmpFile: string, outputFile: string) {
- return sharp(tmpFile)
- .resize(1600, 1600, {
- fit: sharp.fit.inside,
- withoutEnlargement: true
- })
- .jpeg()
- .toFile(outputFile)
- }
- function createThumbnail(tmpFile: string, thumbnail: string) {
- return sharp(tmpFile)
- .resize(200, 200, {
- fit: sharp.fit.inside
- })
- .jpeg()
- .toFile(thumbnail)
- }
|