Quellcode durchsuchen

@uppy/compressor: update file.meta.name after compression, becase format/extension might have changed (#4645)

* When Compressor changed file format, update file.meta.name

* only use the setFileState, update comment

* Use Compressor ESM, check for name and extension

* Add test with mocked compress()

* Test user changing the file.meta.name

* Update packages/@uppy/compressor/package.json

Co-authored-by: Antoine du Hamel <antoine@transloadit.com>

* Cleaner variables, remove excessive checks

* Fix package.json

---------

Co-authored-by: Antoine du Hamel <antoine@transloadit.com>
Artur Paikin vor 1 Jahr
Ursprung
Commit
8b86db1ce5

+ 3 - 0
packages/@uppy/compressor/package.json

@@ -34,5 +34,8 @@
   },
   "publishConfig": {
     "access": "public"
+  },
+  "devDependencies": {
+    "@jest/globals": "^29.0.0"
   }
 }

+ 14 - 4
packages/@uppy/compressor/src/index.js

@@ -2,7 +2,7 @@ import { BasePlugin } from '@uppy/core'
 import { RateLimitedQueue } from '@uppy/utils/lib/RateLimitedQueue'
 import getFileNameAndExtension from '@uppy/utils/lib/getFileNameAndExtension'
 import prettierBytes from '@transloadit/prettier-bytes'
-import CompressorJS from 'compressorjs/dist/compressor.common.js'
+import CompressorJS from 'compressorjs'
 import locale from './locale.js'
 
 export default class Compressor extends BasePlugin {
@@ -52,15 +52,25 @@ export default class Compressor extends BasePlugin {
           this.uppy.log(`[Image Compressor] Image ${file.id} compressed by ${prettierBytes(compressedSavingsSize)}`)
           totalCompressedSize += compressedSavingsSize
           const { name, type, size } = compressedBlob
-          const extension = name && getFileNameAndExtension(name).extension
+
+          const compressedFileName = getFileNameAndExtension(name)
+          const metaFileName = getFileNameAndExtension(file.meta.name)
+
+          // Name (file.meta.name) might have been changed by user, so we update only the extension
+          const newMetaName = `${metaFileName.name}.${compressedFileName.extension}`
+
           this.uppy.setFileState(file.id, {
             ...(name && { name }),
-            ...(extension && { extension }),
+            ...(compressedFileName.extension && { extension: compressedFileName.extension }),
             ...(type && { type }),
             ...(size && { size }),
             data: compressedBlob,
+            meta: {
+              ...file.meta,
+              type,
+              name: newMetaName,
+            },
           })
-          this.uppy.setFileMeta(file.id, { type })
           compressedFiles.push(file)
         } catch (err) {
           this.uppy.log(`[Image Compressor] Failed to compress ${file.id}:`, 'warning')

+ 54 - 0
packages/@uppy/compressor/src/index.test.js

@@ -0,0 +1,54 @@
+import { describe, expect, it } from '@jest/globals'
+import Core from '@uppy/core'
+import getFileNameAndExtension from '@uppy/utils/lib/getFileNameAndExtension'
+import fs from 'node:fs'
+import CompressorPlugin from './index.js'
+
+// Compressor uses browser canvas API, so need to mock compress()
+CompressorPlugin.prototype.compress = (blob) => {
+  return {
+    name: `${getFileNameAndExtension(blob.name).name}.webp`,
+    type: 'image/webp',
+    data: blob,
+    size: 123,
+  }
+}
+
+const sampleImage = fs.readFileSync(new URL('../../../../e2e/cypress/fixtures/images/image.jpg', import.meta.url))
+
+const file1 = { source: 'jest', name: 'image-1.jpeg', type: 'image/jpeg', data: new File([sampleImage], 'image-1.jpeg', { type: 'image/jpeg' }) }
+const file2 = { source: 'jest', name: 'yolo', type: 'image/jpeg', data: new File([sampleImage], 'yolo', { type: 'image/jpeg' }) }
+const file3 = { source: 'jest', name: 'my.file.is.weird.png', type: 'image/png', data: new File([sampleImage], 'my.file.is.weird.png', { type: 'image/png' }) }
+
+describe('CompressorPlugin', () => {
+  it('should change update extension in file.name and file.meta.name', () => {
+    const uppy = new Core()
+    uppy.use(CompressorPlugin, {
+      quality: 0.85,
+      mimeType: 'image/webp',
+    })
+
+    uppy.addFile(file1)
+    uppy.addFile(file2)
+    uppy.addFile(file3)
+
+    // User changed file.meta.name
+    uppy.setFileMeta(uppy.getFiles()[0].id, { name: 'new-name.jpeg' })
+
+    return uppy.upload().then(() => {
+      const files = uppy.getFiles()
+
+      expect(files[0].meta.name).toEqual('new-name.webp')
+      expect(files[0].name).toEqual('image-1.webp')
+      expect(files[0].meta.type).toEqual('image/webp')
+
+      expect(files[1].meta.name).toEqual('yolo.webp')
+      expect(files[1].meta.type).toEqual('image/webp')
+      expect(files[1].name).toEqual('yolo.webp')
+
+      expect(files[2].meta.name).toEqual('my.file.is.weird.webp')
+      expect(files[2].meta.type).toEqual('image/webp')
+      expect(files[2].name).toEqual('my.file.is.weird.webp')
+    })
+  })
+})

+ 1 - 0
yarn.lock

@@ -9653,6 +9653,7 @@ __metadata:
   version: 0.0.0-use.local
   resolution: "@uppy/compressor@workspace:packages/@uppy/compressor"
   dependencies:
+    "@jest/globals": ^29.0.0
     "@transloadit/prettier-bytes": ^0.0.9
     "@uppy/utils": "workspace:^"
     compressorjs: ^1.1.1