(config, filename, data, contentType, options)
| 15 | } |
| 16 | |
| 17 | async createFile(config, filename, data, contentType, options) { |
| 18 | const extname = path.extname(filename); |
| 19 | |
| 20 | const hasExtension = extname.length > 0; |
| 21 | const mime = (await import('mime')).default |
| 22 | if (!hasExtension && contentType && mime.getExtension(contentType)) { |
| 23 | filename = filename + '.' + mime.getExtension(contentType); |
| 24 | } else if (hasExtension) { |
| 25 | contentType = mime.getType(filename) || contentType; |
| 26 | } |
| 27 | |
| 28 | if (!this.options.preserveFileName) { |
| 29 | filename = randomHexString(32) + '_' + filename; |
| 30 | } |
| 31 | |
| 32 | // Prepend directory if provided |
| 33 | if (options && options.directory) { |
| 34 | filename = options.directory + '/' + filename; |
| 35 | delete options.directory; |
| 36 | } |
| 37 | |
| 38 | // Fallback: buffer stream for adapters that don't support streaming |
| 39 | if (typeof data?.pipe === 'function' && !this.adapter.supportsStreaming) { |
| 40 | data = await new Promise((resolve, reject) => { |
| 41 | const chunks = []; |
| 42 | data.on('data', chunk => chunks.push(chunk)); |
| 43 | data.on('end', () => resolve(Buffer.concat(chunks))); |
| 44 | data.on('error', reject); |
| 45 | }); |
| 46 | } |
| 47 | |
| 48 | const location = await this.adapter.getFileLocation(config, filename); |
| 49 | await this.adapter.createFile(filename, data, contentType, options); |
| 50 | return { |
| 51 | url: location, |
| 52 | name: filename, |
| 53 | } |
| 54 | } |
| 55 | |
| 56 | deleteFile(config, filename) { |
| 57 | return this.adapter.deleteFile(filename); |
nothing calls this directly
no test coverage detected