2
0

feat(editor): Add file upload input

This commit is contained in:
Baptiste Arnaud
2022-06-12 17:34:33 +02:00
parent d4c52d47b3
commit 75365a0d82
48 changed files with 1022 additions and 587 deletions

View File

@ -1 +1,2 @@
export * from './utils'
export * from './storage'

View File

@ -0,0 +1,51 @@
import { config, Endpoint, S3 } from 'aws-sdk'
type GeneratePresignedUrlProps = {
filePath: string
fileType: string
}
const tenMB = 10485760
const oneHundredAndTwentySeconds = 120
export const generatePresignedUrl = ({
filePath,
fileType,
}: GeneratePresignedUrlProps): S3.PresignedPost => {
if (
!process.env.S3_ENDPOINT ||
!process.env.S3_ACCESS_KEY ||
!process.env.S3_SECRET_KEY
)
throw new Error(
'S3 not properly configured. Missing one of those variables: S3_ENDPOINT, S3_ACCESS_KEY, S3_SECRET_KEY'
)
const sslEnabled =
process.env.S3_SSL && process.env.S3_SSL === 'false' ? false : true
config.update({
accessKeyId: process.env.S3_ACCESS_KEY,
secretAccessKey: process.env.S3_SECRET_KEY,
region: process.env.S3_REGION,
sslEnabled,
})
const protocol = sslEnabled ? 'https' : 'http'
const s3 = new S3({
endpoint: new Endpoint(
`${protocol}://${process.env.S3_ENDPOINT}${
process.env.S3_PORT ? `:${process.env.S3_PORT}` : ''
}`
),
})
const presignedUrl = s3.createPresignedPost({
Bucket: process.env.S3_BUCKET ?? 'typebot',
Fields: {
key: filePath,
'Content-Type': fileType,
},
Expires: oneHundredAndTwentySeconds,
Conditions: [['content-length-range', 0, tenMB]],
})
return presignedUrl
}

View File

@ -24,7 +24,7 @@ export const sendRequest = async <ResponseData>(
| {
url: string
method: string
body?: Record<string, unknown>
body?: Record<string, unknown> | FormData
}
| string
): Promise<{ data?: ResponseData; error?: Error }> => {
@ -191,3 +191,53 @@ export const generateId = (idDesiredLength: number): string => {
})
.join('')
}
type UploadFileProps = {
files: {
file: File
path: string
}[]
onUploadProgress?: (percent: number) => void
}
type UrlList = string[]
export const uploadFiles = async ({
files,
onUploadProgress,
}: UploadFileProps): Promise<UrlList> => {
const requests = files.map(async ({ file, path }) => {
const { data } = await sendRequest<{
presignedUrl: { url: string; fields: any }
}>(
`/api/storage/upload-url?filePath=${encodeURIComponent(path)}&fileType=${
file.type
}`
)
if (!data?.presignedUrl) return null
const { url, fields } = data.presignedUrl
const formData = new FormData()
Object.entries({ ...fields, file }).forEach(([key, value]) => {
formData.append(key, value as string | Blob)
})
const upload = await fetch(url, {
method: 'POST',
body: formData,
})
if (!upload.ok) return
return `${url.split('?')[0]}/${path}`
})
const urls = []
let i = 0
for (const request of requests) {
i += 1
const url = await request
onUploadProgress && onUploadProgress((i / requests.length) * 100)
if (!url) continue
urls.push(url)
}
return urls
}