upload endpoint moved from vercel to backend (#119)
This commit is contained in:
parent
9504fada02
commit
cf0c4455f3
|
@ -1,14 +0,0 @@
|
||||||
import formidable from 'formidable'
|
|
||||||
|
|
||||||
export const formidablePromise = async (request, options) => {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const form = formidable(options)
|
|
||||||
|
|
||||||
form.parse(request, (err, fields, files) => {
|
|
||||||
if (err) {
|
|
||||||
return reject(err)
|
|
||||||
}
|
|
||||||
return resolve({ fields, files })
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
|
@ -1,76 +0,0 @@
|
||||||
import { S3Client } from '@aws-sdk/client-s3'
|
|
||||||
import { Upload } from '@aws-sdk/lib-storage'
|
|
||||||
import formidable from 'formidable'
|
|
||||||
import { Writable } from 'stream'
|
|
||||||
import path from 'path'
|
|
||||||
import crypto from 'crypto'
|
|
||||||
import { formidablePromise } from './_shared/formidablePromise.js'
|
|
||||||
|
|
||||||
const { STORJ_ACCESS_KEY, STORJ_SECRET_KEY, STORJ_END_POINT, STORJ_BUCKET_NAME, CDN_DOMAIN } = process.env
|
|
||||||
|
|
||||||
const storjS3Client = new S3Client({
|
|
||||||
endpoint: STORJ_END_POINT,
|
|
||||||
credentials: {
|
|
||||||
accessKeyId: STORJ_ACCESS_KEY,
|
|
||||||
secretAccessKey: STORJ_SECRET_KEY
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const fileConsumer = (acc) => {
|
|
||||||
return new Writable({
|
|
||||||
write: (chunk, _enc, next) => {
|
|
||||||
acc.push(chunk)
|
|
||||||
next()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const formidableConfig = {
|
|
||||||
keepExtensions: true,
|
|
||||||
maxFileSize: 10_000_000,
|
|
||||||
maxFieldsSize: 10_000_000,
|
|
||||||
maxFields: 7,
|
|
||||||
allowEmptyFiles: false,
|
|
||||||
multiples: false
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleFileUpload = async (request) => {
|
|
||||||
const chunks = []
|
|
||||||
const { files } = await formidablePromise(request, {
|
|
||||||
...formidableConfig,
|
|
||||||
// consume this, otherwise formidable tries to save the file to disk
|
|
||||||
fileWriteStreamHandler: () => fileConsumer(chunks)
|
|
||||||
})
|
|
||||||
|
|
||||||
const data = Buffer.concat(chunks)
|
|
||||||
|
|
||||||
const { originalFilename, mimetype } = files.file
|
|
||||||
|
|
||||||
const fileExtension = path.extname(originalFilename)
|
|
||||||
|
|
||||||
const filename = crypto.randomUUID() + fileExtension
|
|
||||||
|
|
||||||
const params = {
|
|
||||||
Bucket: STORJ_BUCKET_NAME,
|
|
||||||
Key: filename,
|
|
||||||
Body: data,
|
|
||||||
ContentType: mimetype
|
|
||||||
}
|
|
||||||
|
|
||||||
const upload = new Upload({ params, client: storjS3Client })
|
|
||||||
await upload.done()
|
|
||||||
|
|
||||||
return `http://${CDN_DOMAIN}/${filename}`
|
|
||||||
}
|
|
||||||
|
|
||||||
const handler = async (request, response) => {
|
|
||||||
try {
|
|
||||||
const location = await handleFileUpload(request)
|
|
||||||
return response.status(200).json(location)
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error)
|
|
||||||
response.status(500).json({ error: error.message })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default handler
|
|
12
package.json
12
package.json
|
@ -29,18 +29,11 @@
|
||||||
"typecheck:watch": "tsc --noEmit --watch"
|
"typecheck:watch": "tsc --noEmit --watch"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-sdk/abort-controller": "3.303.0",
|
|
||||||
"@aws-sdk/client-s3": "3.303.0",
|
|
||||||
"@aws-sdk/lib-storage": "3.303.0",
|
|
||||||
"@hocuspocus/provider": "2.0.6",
|
"@hocuspocus/provider": "2.0.6",
|
||||||
"@solid-primitives/media": "2.2.3",
|
|
||||||
"form-data": "4.0.0",
|
"form-data": "4.0.0",
|
||||||
"formidable": "2.1.1",
|
|
||||||
"i18next": "22.4.15",
|
"i18next": "22.4.15",
|
||||||
"mailgun.js": "8.2.1",
|
"mailgun.js": "8.2.1",
|
||||||
"node-fetch": "3.3.1",
|
"node-fetch": "3.3.1"
|
||||||
"solid-popper": "0.3.0",
|
|
||||||
"typograf": "7.1.0"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "7.21.8",
|
"@babel/core": "7.21.8",
|
||||||
|
@ -54,6 +47,7 @@
|
||||||
"@nanostores/router": "0.8.3",
|
"@nanostores/router": "0.8.3",
|
||||||
"@nanostores/solid": "0.3.2",
|
"@nanostores/solid": "0.3.2",
|
||||||
"@popperjs/core": "2.11.7",
|
"@popperjs/core": "2.11.7",
|
||||||
|
"@solid-primitives/media": "2.2.3",
|
||||||
"@solid-primitives/memo": "1.2.4",
|
"@solid-primitives/memo": "1.2.4",
|
||||||
"@solid-primitives/share": "2.0.4",
|
"@solid-primitives/share": "2.0.4",
|
||||||
"@solid-primitives/storage": "1.3.9",
|
"@solid-primitives/storage": "1.3.9",
|
||||||
|
@ -155,6 +149,7 @@
|
||||||
"rollup-plugin-visualizer": "5.9.0",
|
"rollup-plugin-visualizer": "5.9.0",
|
||||||
"sass": "1.62.1",
|
"sass": "1.62.1",
|
||||||
"solid-js": "1.7.5",
|
"solid-js": "1.7.5",
|
||||||
|
"solid-popper": "0.3.0",
|
||||||
"solid-tiptap": "0.6.0",
|
"solid-tiptap": "0.6.0",
|
||||||
"solid-transition-group": "0.2.2",
|
"solid-transition-group": "0.2.2",
|
||||||
"sort-package-json": "2.4.1",
|
"sort-package-json": "2.4.1",
|
||||||
|
@ -165,6 +160,7 @@
|
||||||
"swiper": "9.4.1",
|
"swiper": "9.4.1",
|
||||||
"ts-node": "10.9.1",
|
"ts-node": "10.9.1",
|
||||||
"typescript": "5.0.4",
|
"typescript": "5.0.4",
|
||||||
|
"typograf": "7.1.0",
|
||||||
"undici": "5.21.0",
|
"undici": "5.21.0",
|
||||||
"uniqolor": "1.1.0",
|
"uniqolor": "1.1.0",
|
||||||
"unique-names-generator": "4.7.1",
|
"unique-names-generator": "4.7.1",
|
||||||
|
|
|
@ -26,8 +26,8 @@ export const UploadModalContent = (props: Props) => {
|
||||||
const runUpload = async (file) => {
|
const runUpload = async (file) => {
|
||||||
try {
|
try {
|
||||||
setIsUploading(true)
|
setIsUploading(true)
|
||||||
const fileUrl = await handleFileUpload(file)
|
const result = await handleFileUpload(file)
|
||||||
props.onClose(fileUrl)
|
props.onClose(result.url)
|
||||||
setIsUploading(false)
|
setIsUploading(false)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setIsUploading(false)
|
setIsUploading(false)
|
||||||
|
|
|
@ -29,7 +29,7 @@ export const DropArea = (props: Props) => {
|
||||||
const results: string[] = []
|
const results: string[] = []
|
||||||
for (const file of files) {
|
for (const file of files) {
|
||||||
const result = await handleFileUpload(file)
|
const result = await handleFileUpload(file)
|
||||||
results.push(result)
|
results.push(result.url)
|
||||||
}
|
}
|
||||||
props.onUpload(results)
|
props.onUpload(results)
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
|
|
|
@ -106,7 +106,7 @@ export const SolidSwiper = (props: Props) => {
|
||||||
const results: string[] = []
|
const results: string[] = []
|
||||||
for (const file of selectedFiles) {
|
for (const file of selectedFiles) {
|
||||||
const result = await handleFileUpload(file)
|
const result = await handleFileUpload(file)
|
||||||
results.push(result)
|
results.push(result.url)
|
||||||
}
|
}
|
||||||
props.onImagesAdd(composeMediaItem(results))
|
props.onImagesAdd(composeMediaItem(results))
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
|
|
|
@ -61,8 +61,8 @@ export const ProfileSettingsPage = () => {
|
||||||
await selectFiles(async ([uploadFile]) => {
|
await selectFiles(async ([uploadFile]) => {
|
||||||
try {
|
try {
|
||||||
setIsUserpicUpdating(true)
|
setIsUserpicUpdating(true)
|
||||||
const fileUrl = await handleFileUpload(uploadFile)
|
const result = await handleFileUpload(uploadFile)
|
||||||
updateFormField('userpic', fileUrl)
|
updateFormField('userpic', result.url)
|
||||||
setIsUserpicUpdating(false)
|
setIsUserpicUpdating(false)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('[upload avatar] error', error)
|
console.error('[upload avatar] error', error)
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import { UploadFile } from '@solid-primitives/upload'
|
import { UploadFile } from '@solid-primitives/upload'
|
||||||
import { isDev } from './config'
|
import { apiBaseUrl } from './config'
|
||||||
|
|
||||||
const api = isDev ? 'https://new.discours.io/api/upload' : '/api/upload'
|
const apiUrl = `${apiBaseUrl}/upload`
|
||||||
|
|
||||||
export const handleFileUpload = async (uploadFile: UploadFile) => {
|
export const handleFileUpload = async (uploadFile: UploadFile) => {
|
||||||
const formData = new FormData()
|
const formData = new FormData()
|
||||||
formData.append('file', uploadFile.file, uploadFile.name)
|
formData.append('file', uploadFile.file, uploadFile.name)
|
||||||
const response = await fetch(api, {
|
const response = await fetch(apiUrl, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: formData
|
body: formData
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue
Block a user