Strip EXIF data before upload on client (#634)

Co-authored-by: ekzyis <ek@stacker.news>
This commit is contained in:
ekzyis 2023-11-19 21:22:46 +01:00 committed by GitHub
parent a318727f9c
commit 158baa61e3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 41 additions and 1 deletions

View File

@ -150,8 +150,9 @@ export const ImageUpload = forwardRef(({ children, className, onSelect, onUpload
}
}`)
const s3Upload = useCallback(file => {
const s3Upload = useCallback(async file => {
const img = new window.Image()
file = await removeExifData(file)
img.src = window.URL.createObjectURL(file)
return new Promise((resolve, reject) => {
img.onload = async () => {
@ -232,3 +233,42 @@ export const ImageUpload = forwardRef(({ children, className, onSelect, onUpload
</>
)
})
// from https://stackoverflow.com/a/77472484
const removeExifData = (file) => {
const cleanBuffer = (arrayBuffer) => {
let dataView = new DataView(arrayBuffer)
const exifMarker = 0xffe1
let offset = 2 // Skip the first two bytes (0xFFD8)
while (offset < dataView.byteLength) {
if (dataView.getUint16(offset) === exifMarker) {
// Found an EXIF marker
const segmentLength = dataView.getUint16(offset + 2, false) + 2
arrayBuffer = removeSegment(arrayBuffer, offset, segmentLength)
dataView = new DataView(arrayBuffer)
} else {
// Move to the next marker
offset += 2 + dataView.getUint16(offset + 2, false)
}
}
return arrayBuffer
}
const removeSegment = (buffer, offset, length) => {
// Create a new buffer without the specified segment
const modifiedBuffer = new Uint8Array(buffer.byteLength - length)
modifiedBuffer.set(new Uint8Array(buffer.slice(0, offset)), 0)
modifiedBuffer.set(new Uint8Array(buffer.slice(offset + length)), offset)
return modifiedBuffer.buffer
}
return new Promise((resolve) => {
if (!file || !file.type.startsWith('image/')) return resolve(file)
const fr = new window.FileReader()
fr.onload = function () {
const cleanedBuffer = cleanBuffer(this.result)
const blob = new Blob([cleanedBuffer], { type: file.type })
const newFile = new File([blob], file.name, { type: file.type })
resolve(newFile)
}
fr.readAsArrayBuffer(file)
})
}