feat(medusa-file-local): implement missing streaming methods (#4788)

This commit is contained in:
Frane Polić
2023-08-23 13:05:04 +02:00
committed by GitHub
parent 4843cc6301
commit d8a6e3e0d8
10 changed files with 189 additions and 107 deletions
@@ -1,11 +1,13 @@
import { AbstractFileService, IFileService } from "@medusajs/medusa"
import {
AbstractFileService,
FileServiceGetUploadStreamResult,
FileServiceUploadResult,
IFileService,
} from "@medusajs/medusa"
UploadStreamDescriptorType,
} from "@medusajs/types"
import fs from "fs"
import { parse } from "path"
import path from "path"
import stream from "stream"
class LocalService extends AbstractFileService implements IFileService {
protected uploadDir_: string
@@ -14,7 +16,7 @@ class LocalService extends AbstractFileService implements IFileService {
constructor({}, options) {
super({}, options)
this.uploadDir_ = options.upload_dir || "uploads/images"
this.uploadDir_ = options.upload_dir || "uploads"
this.backendUrl_ = options.backend_url || "http://localhost:9000"
}
@@ -29,40 +31,91 @@ class LocalService extends AbstractFileService implements IFileService {
async uploadFile(
file: Express.Multer.File,
options = {}
): Promise<{ url: string }> {
const parsedFilename = parse(file.originalname)
): Promise<FileServiceUploadResult> {
const parsedFilename = path.parse(file.originalname)
const fileKey = `${parsedFilename.name}-${Date.now()}${parsedFilename.ext}`
if (parsedFilename.dir) {
this.ensureDirExists(parsedFilename.dir)
}
const fileKey = path.join(
parsedFilename.dir,
`${Date.now()}-${parsedFilename.base}`
)
return new Promise((resolve, reject) => {
fs.copyFile(file.path, `${this.uploadDir_}/${fileKey}`, (err) => {
if (err) {
reject(err)
throw err
}
const fileUrl = `${this.backendUrl_}/${this.uploadDir_}/${fileKey}`
resolve({ url: fileUrl })
resolve({ url: fileUrl, key: fileKey })
})
})
}
async delete(file): Promise<void> {
throw Error("Not implemented")
const filePath = `${this.uploadDir_}/${file.fileKey}`
if (fs.existsSync(filePath)) {
fs.unlinkSync(filePath)
}
}
async getUploadStreamDescriptor(
fileData
fileData: UploadStreamDescriptorType
): Promise<FileServiceGetUploadStreamResult> {
throw Error("Not implemented")
const parsedFilename = path.parse(
fileData.name + (fileData.ext ? `.${fileData.ext}` : "")
)
if (parsedFilename.dir) {
this.ensureDirExists(parsedFilename.dir)
}
const fileKey = path.join(
parsedFilename.dir,
`${Date.now()}-${parsedFilename.base}`
)
const fileUrl = `${this.backendUrl_}/${this.uploadDir_}/${fileKey}`
const pass = new stream.PassThrough()
const writeStream = fs.createWriteStream(`${this.uploadDir_}/${fileKey}`)
pass.pipe(writeStream) // for consistency with the IFileService
const promise = new Promise((res, rej) => {
writeStream.on("finish", res)
writeStream.on("error", rej)
})
return { url: fileUrl, fileKey, writeStream: pass, promise }
}
async getDownloadStream(fileData): Promise<NodeJS.ReadableStream> {
throw Error("Not implemented")
const filePath = `${this.uploadDir_}/${fileData.fileKey}`
return fs.createReadStream(filePath)
}
async getPresignedDownloadUrl(fileData): Promise<string> {
throw Error("Not implemented")
return `${this.backendUrl_}/${this.uploadDir_}/${fileData.fileKey}`
}
/**
* Ensure `uploadDir_` has nested directories provided as file path
*
* @param dirPath - file path relative to the base directory
* @private
*/
private ensureDirExists(dirPath: string) {
const relativePath = path.join(this.uploadDir_, dirPath)
if (!fs.existsSync(relativePath)) {
fs.mkdirSync(relativePath, { recursive: true })
}
}
}