Skip to content

Commit

Permalink
feat: pdf support via imgproxy
Browse files Browse the repository at this point in the history
  • Loading branch information
Soxasora committed Nov 22, 2024
1 parent 83341d5 commit 90e6e03
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 15 deletions.
26 changes: 16 additions & 10 deletions components/file-upload.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ export const FileUpload = forwardRef(({ children, className, onSelect, onUpload,
const s3Upload = useCallback(async file => {
const element = file.type.startsWith('image/')
? new window.Image()
: document.createElement('video')
: file.type.startsWith('video/')
? document.createElement('video')
: document.createElement('object') // pdf

file = await removeExifData(file)

Expand Down Expand Up @@ -72,16 +74,20 @@ export const FileUpload = forwardRef(({ children, className, onSelect, onUpload,
resolve(id)
}

// img fire 'load' event while videos fire 'loadeddata'
element.onload = onload
element.onloadeddata = onload
if (file.type === 'application/pdf') {
onload() // pdf can be loaded directly
} else {
// img fire 'load' event while videos fire 'loadeddata'
element.onload = onload
element.onloadeddata = onload

element.onerror = reject
element.src = window.URL.createObjectURL(file)
element.onerror = reject
element.src = window.URL.createObjectURL(file)

// iOS Force the video to load metadata
if (element.tagName === 'VIDEO') {
element.load()
// iOS Force the video to load metadata
if (element.tagName === 'VIDEO') {
element.load()
}
}
})
}, [toaster, getSignedPOST])
Expand All @@ -101,7 +107,7 @@ export const FileUpload = forwardRef(({ children, className, onSelect, onUpload,
for (const file of Array.from(fileList)) {
try {
if (accept.indexOf(file.type) === -1) {
throw new Error(`file must be ${accept.map(t => t.replace(/^(image|video)\//, '')).join(', ')}`)
throw new Error(`file must be ${accept.map(t => t.replace(/^(image|video|application)\//, '')).join(', ')}`)
}
if (onSelect) await onSelect?.(file, s3Upload)
else await s3Upload(file)
Expand Down
3 changes: 2 additions & 1 deletion lib/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ export const UPLOAD_TYPES_ALLOW = [
'image/webp',
'video/mp4',
'video/mpeg',
'video/webm'
'video/webm',
'application/pdf'
]
export const AVATAR_TYPES_ALLOW = UPLOAD_TYPES_ALLOW.filter(t => t.startsWith('image/'))
export const INVOICE_ACTION_NOTIFICATION_TYPES = ['ITEM_CREATE', 'ZAP', 'DOWN_ZAP', 'POLL_VOTE', 'BOOST']
Expand Down
13 changes: 9 additions & 4 deletions worker/imgproxy.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,11 +123,16 @@ const getMetadata = async (url) => {
const options = '/vm:1/d:1/f:1'
const imgproxyUrl = new URL(createImgproxyPath({ url, options, pathname: '/info' }), IMGPROXY_URL).toString()
const res = await fetch(imgproxyUrl)
const { width, height, format, video_streams: videoStreams } = await res.json()
return { dimensions: { width, height }, format, video: !!videoStreams?.length }
const { width, height, format, pages, video_streams: videoStreams } = await res.json()
return { dimensions: { width, height }, format, video: !!videoStreams?.length, pdf: format === 'pdf', pages: pages || 1 }
}

const createImgproxyPath = ({ url, pathname = '/', options }) => {
// pdf processing, pg:1 for first page, q:90 for quality, cc:ffffff for white background, dpr:2 for retina
if (url.endsWith('.pdf')) {
options = `/pg:1${options}/q:90/cc:ffffff/dpr:2`
}

const b64Url = Buffer.from(url, 'utf-8').toString('base64url')
const target = path.join(options, b64Url)
const signature = sign(target)
Expand All @@ -151,7 +156,7 @@ const isMediaURL = async (url, { forceFetch }) => {
// https://stackoverflow.com/a/68118683
const res = await fetchWithTimeout(url, { timeout: 1000, method: 'HEAD' })
const buf = await res.blob()
isMedia = buf.type.startsWith('image/') || buf.type.startsWith('video/')
isMedia = buf.type.startsWith('image/') || buf.type.startsWith('video/' || buf.type === 'application/pdf')
} catch (err) {
console.log(url, err)
}
Expand All @@ -167,7 +172,7 @@ const isMediaURL = async (url, { forceFetch }) => {
try {
const res = await fetchWithTimeout(url, { timeout: 10000 })
const buf = await res.blob()
isMedia = buf.type.startsWith('image/') || buf.type.startsWith('video/')
isMedia = buf.type.startsWith('image/') || buf.type.startsWith('video/' || buf.type === 'application/pdf')
} catch (err) {
console.log(url, err)
}
Expand Down

0 comments on commit 90e6e03

Please sign in to comment.