Skip to content

Commit

Permalink
feat: 文件在线预览支持更多的文件类型 #2765
Browse files Browse the repository at this point in the history
1.review意见修改
  • Loading branch information
liuliaozhong committed Dec 25, 2024
1 parent 1d84f7a commit f495c1c
Show file tree
Hide file tree
Showing 16 changed files with 163 additions and 288 deletions.
1 change: 0 additions & 1 deletion src/backend/buildSrc/src/main/kotlin/Versions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -76,5 +76,4 @@ object Versions {
const val Galimatias = "0.2.1"
const val CommonsNet = "3.9.0"
const val JuniversalCharDet = "1.0.3"
const val HttpClient = "4.5.13"
}
1 change: 0 additions & 1 deletion src/backend/preview/biz-preview/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ dependencies {
//api(project(":common:common-generic"))
api(project(":common:common-artifact:artifact-service"))
api("org.dom4j:dom4j:${Versions.Dom4j}")
api("org.apache.httpcomponents:httpclient:${Versions.HttpClient}")
// office转换
api("org.jodconverter:jodconverter-local:${Versions.JodConverter}")
// url规范化
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ class PreviewConfig {
@Value("\${preview.repoName:convert}")
val repoName = "convert"

/**
* repo是否公开
*/
@Value("\${preview.repoPublic:true}")
val repoPublic = true

/**
* 临时文件保存路径
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,10 @@ import com.tencent.bkrepo.common.artifact.pojo.configuration.local.LocalConfigur
import com.tencent.bkrepo.common.metadata.service.project.ProjectService
import com.tencent.bkrepo.common.metadata.service.repo.RepositoryService
import com.tencent.bkrepo.preview.config.configuration.PreviewConfig
import com.tencent.bkrepo.repository.constant.SYSTEM_USER
import com.tencent.bkrepo.repository.pojo.project.ProjectCreateRequest
import com.tencent.bkrepo.repository.pojo.repo.RepoCreateRequest
import com.tencent.bkrepo.repository.pojo.repo.RepoUpdateRequest
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.boot.ApplicationArguments
Expand Down Expand Up @@ -74,27 +76,36 @@ class PreviewStartupRunner(
val projectId = config.projectId
val repoName = config.repoName
var exist = repositoryService.checkExist(projectId, repoName, RepositoryType.GENERIC.name)
if (!exist) {
val repoConfig = LocalConfiguration()
val cleanupStrategy = mutableMapOf(
"enable" to true,
"cleanupType" to "retentionDays",
"cleanupValue" to config.artifactKeepDays
)
repoConfig.settings["cleanupStrategy"] = cleanupStrategy
val repoConfig = LocalConfiguration()
val cleanupStrategy = mutableMapOf(
"enable" to true,
"cleanupType" to "retentionDays",
"cleanupValue" to config.artifactKeepDays
)
repoConfig.settings["cleanupStrategy"] = cleanupStrategy

if (!exist) {
val req = RepoCreateRequest(projectId = config.projectId,
name = config.repoName,
type = RepositoryType.GENERIC,
category = RepositoryCategory.LOCAL,
public = true,
public = config.repoPublic,
quota = config.repoQuota * 1024 * 1024,
configuration =repoConfig
)
var createdRepo = repositoryService.createRepo(req)
logger.debug("Create project success,projectId:${createdRepo.name}")
} else {
logger.debug("project ${config.projectId} and repository ${config.repoName} exist skip.")
logger.debug("project ${config.projectId} and repository ${config.repoName} exist. to update")
val updateRepo = RepoUpdateRequest(
projectId = config.projectId,
name = config.repoName,
public = config.repoPublic,
quota = config.repoQuota * 1024 * 1024,
configuration =repoConfig,
operator = SYSTEM_USER
)
repositoryService.updateRepo(updateRepo)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,22 +34,30 @@ package com.tencent.bkrepo.preview.dao
import com.mongodb.client.result.DeleteResult
import com.tencent.bkrepo.common.mongo.dao.simple.SimpleMongoDao
import com.tencent.bkrepo.preview.model.TPreviewFileCache
import org.springframework.data.mongodb.core.query.Criteria
import org.springframework.data.mongodb.core.query.Query
import org.springframework.data.mongodb.core.query.isEqualTo
import org.springframework.stereotype.Repository

@Repository
class FilePreviewCacheDao : SimpleMongoDao<TPreviewFileCache>() {
/**
* 按md5查找
* 查找缓存
*/
fun findByMd5(md5: String): TPreviewFileCache? {
return this.findOne(Query(TPreviewFileCache::md5.isEqualTo(md5)))
fun getCache(md5: String, projectId: String, repoName: String): TPreviewFileCache? {
return this.findOne(Query(buildCriteria(md5, projectId, repoName)))
}
/**
* 按md5删除
* 删除缓存
*/
fun removeByMd5(md5: String): DeleteResult {
return this.remove(Query(TPreviewFileCache::md5.isEqualTo(md5)))
fun removeCache(md5: String, projectId: String, repoName: String): DeleteResult {
return this.remove(Query(buildCriteria(md5, projectId, repoName)))
}

private fun buildCriteria(md5: String, projectId: String, repoName: String): Criteria {
return Criteria
.where(TPreviewFileCache::md5.name).isEqualTo(md5)
.and(TPreviewFileCache::projectId.name).isEqualTo(projectId)
.and(TPreviewFileCache::repoName.name).isEqualTo(repoName)
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package com.tencent.bkrepo.preview.service

import com.tencent.bkrepo.common.api.util.readJsonString
import com.tencent.bkrepo.preview.config.configuration.PreviewConfig
import com.tencent.bkrepo.preview.pojo.PreviewOptions
import com.tencent.bkrepo.preview.pojo.Watermark
import com.tencent.bkrepo.preview.utils.JsonMapper
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.stereotype.Component
Expand All @@ -19,9 +19,8 @@ class CommonResourceService(private val config: PreviewConfig) {
* 水印
*/
fun getWatermark(decodedParams: String?): Watermark {
val jsonMapper = JsonMapper()
val watermark = if (!decodedParams.isNullOrEmpty()) {
jsonMapper.fromJson(decodedParams, Watermark::class.java)?: Watermark()
decodedParams!!.readJsonString()
} else {
Watermark()
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.tencent.bkrepo.preview.service

import com.tencent.bkrepo.common.api.util.readJsonString
import com.tencent.bkrepo.common.artifact.api.ArtifactInfo
import com.tencent.bkrepo.preview.config.configuration.PreviewConfig
import com.tencent.bkrepo.preview.constant.PreviewMessageCode
Expand All @@ -8,7 +9,6 @@ import com.tencent.bkrepo.preview.pojo.FileAttribute
import com.tencent.bkrepo.preview.pojo.FileType
import com.tencent.bkrepo.preview.pojo.PreviewInfo
import com.tencent.bkrepo.preview.utils.FileUtils
import com.tencent.bkrepo.preview.utils.JsonMapper
import com.tencent.bkrepo.preview.utils.UrlEncoderUtils
import com.tencent.bkrepo.preview.utils.WebUtils
import org.slf4j.LoggerFactory
Expand Down Expand Up @@ -73,7 +73,6 @@ class FileHandlerService(
*/
fun getFileTemplate(fileAttribute: FileAttribute): String = with(fileAttribute) {
when {
isHtmlView && suffix?.lowercase() == "csv" -> FilePreview.CSV_FILE_PREVIEW_PAGE
isHtmlView -> FilePreview.EXEL_FILE_PREVIEW_PAGE
type?.name == FileType.OFFICE.name -> when (suffix!!.lowercase()) {
"xlsx" -> FilePreview.XLSX_FILE_PREVIEW_PAGE
Expand All @@ -99,8 +98,7 @@ class FileHandlerService(
* @return 文件属性
*/
fun getFileAttribute(params: String): FileAttribute {
val jsonMapper = JsonMapper()
val attribute = jsonMapper.fromJson(params, FileAttribute::class.java)?: FileAttribute()
val attribute = params.readJsonString<FileAttribute>()
checkRequest(attribute)
adjustProperties(attribute)
return attribute
Expand All @@ -113,8 +111,7 @@ class FileHandlerService(
* @return 文件属性
*/
fun getFileAttribute(artifactInfo: ArtifactInfo, params: String?): FileAttribute {
val jsonMapper = JsonMapper()
val attribute = jsonMapper.fromJson(params, FileAttribute::class.java)?: FileAttribute()
val attribute = params?.readJsonString<FileAttribute>() ?: FileAttribute()
attribute.projectId = artifactInfo.projectId
attribute.repoName = artifactInfo.repoName
attribute.artifactUri = artifactInfo.getArtifactFullPath()
Expand Down Expand Up @@ -265,7 +262,7 @@ class FileHandlerService(

// 判断是否为HTML视图
private fun isHtmlView(suffix: String): Boolean {
val htmlSuffixes = setOf("xls", "csv", "xlsm", "xlt", "xltm", "et", "ett", "xlam")
val htmlSuffixes = setOf("xls", "xlsm", "xlt", "xltm", "et", "ett", "xlam")
return htmlSuffixes.contains(suffix.lowercase())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@

package com.tencent.bkrepo.preview.service

import javax.annotation.PostConstruct
import javax.annotation.PreDestroy
import org.apache.commons.lang3.StringUtils
import org.jodconverter.core.office.InstalledOfficeManagerHolder
Expand All @@ -52,7 +51,7 @@ import java.io.IOException
*/
@Component
class OfficePluginManager {
private lateinit var officeManager: LocalOfficeManager
private var officeManager: LocalOfficeManager ? = null

@Value("\${preview.office.plugin.server.ports:2001,2002}")
private val serverPorts = "2001,2002"
Expand All @@ -69,11 +68,16 @@ class OfficePluginManager {
@Value("\${preview.office.home:/opt/libreoffice7.6}")
private val officeHome: String = "/opt/libreoffice7.6"

fun startOfficeManagerIfNeeded() {
if (officeManager == null) {
startOfficeManager()
}
}

/**
* 启动Office组件进程
*/
@PostConstruct
fun startOfficeManager() {
private fun startOfficeManager() {
val officeHome: File = getOfficeHome(officeHome)
logger.info("Office component path:${officeHome.path}")
val killOffice = killProcess()
Expand All @@ -92,7 +96,7 @@ class OfficePluginManager {
.maxTasksPerProcess(maxTasksPerProcess)
.taskExecutionTimeout(taskexecutiontimeout)
.build()
officeManager.start()
officeManager?.start()
InstalledOfficeManagerHolder.setInstance(officeManager)
} catch (e: Exception) {
logger.error("The office component fails to start, check whether the office component is available",e)
Expand Down Expand Up @@ -165,7 +169,7 @@ class OfficePluginManager {

@PreDestroy
fun destroyOfficeManager() {
if (null != officeManager && officeManager.isRunning()) {
if (null != officeManager && officeManager!!.isRunning()) {
logger.info("Shutting down office process")
OfficeUtils.stopQuietly(officeManager)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,18 @@ import java.io.File
* office转pdf服务
*/
@Component
class OfficeToPdfService(private val config: PreviewConfig) {
class OfficeToPdfService(
private val config: PreviewConfig,
private val officePluginManager: OfficePluginManager
) {

companion object {
private val logger: Logger = LoggerFactory.getLogger(OfficeToPdfService::class.java)
}

@Throws(OfficeException::class)
fun openOfficeToPDF(inputFilePath: String, outputFilePath: String, fileAttribute: FileAttribute) {
officePluginManager.startOfficeManagerIfNeeded()
office2pdf(inputFilePath, outputFilePath, fileAttribute)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ interface PreviewFileCacheService {
fun createCache(requestFile: PreviewFileCacheCreateRequest): PreviewFileCacheInfo

// 删除缓存
fun removeCacheByMd5(md5: String)
fun removeCache(md5: String, projectId: String, repoName: String)

// 根据md5查询缓存
fun getCacheByMd5(md5: String): PreviewFileCacheInfo?
// 查询缓存
fun getCache(md5: String, projectId: String, repoName: String): PreviewFileCacheInfo?
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,12 @@ class PreviewFileCacheServiceImpl(
return convert(filePreviewCache)
}

override fun removeCacheByMd5(md5: String) {
filePreviewCacheDao.removeByMd5(md5)
override fun removeCache(md5: String, projectId: String, repoName: String) {
filePreviewCacheDao.removeCache(md5, projectId, repoName)
}

override fun getCacheByMd5(md5: String): PreviewFileCacheInfo? {
return filePreviewCacheDao.findByMd5(md5)?.let { convert(it) }
override fun getCache(md5: String, projectId: String, repoName: String): PreviewFileCacheInfo? {
return filePreviewCacheDao.getCache(md5, projectId, repoName)?.let { convert(it) }
}

private fun convert(previewFileCache: TPreviewFileCache): PreviewFileCacheInfo {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,9 @@ abstract class AbstractFilePreview(
val downloadResult = downloadFile(fileAttribute)
?: throw PreviewNotFoundException(PreviewMessageCode.PREVIEW_FILE_NOT_FOUND, fileAttribute.fileName!!)

// 从缓存获取最终文件并且节点是否存在
var previewFileCacheInfo = if (config.cacheEnabled) getCacheAndCheckExist(fileAttribute.md5!!) else null
// 从缓存获取最终文件并且判断节点是否存在
var previewFileCacheInfo = if (config.cacheEnabled) getCacheAndCheckExist(fileAttribute) else null

if (previewFileCacheInfo == null) {
// 文件校验,比如是否超过最大预览限制
checkFileConstraints(fileAttribute)
Expand Down Expand Up @@ -147,8 +148,11 @@ abstract class AbstractFilePreview(
/**
* 获取预览文件缓存
*/
private fun getCacheAndCheckExist(md5: String): PreviewFileCacheInfo? {
val filePreviewCacheInfo = previewFileCacheService.getCacheByMd5(md5) ?: return null
private fun getCacheAndCheckExist(fileAttribute: FileAttribute): PreviewFileCacheInfo? {
val projectId = if (fileAttribute.storageType == 0) fileAttribute.projectId else config.projectId
val repoName = if (fileAttribute.storageType == 0) fileAttribute.repoName else config.repoName
val md5 = fileAttribute.md5
val filePreviewCacheInfo = previewFileCacheService.getCache(md5!!, projectId!!, repoName!!) ?: return null
// 检查节点是否存在
return if (nodeService.checkExist(
ArtifactInfo(
Expand All @@ -161,7 +165,7 @@ abstract class AbstractFilePreview(
filePreviewCacheInfo
} else {
// 节点不存在,移除缓存
previewFileCacheService.removeCacheByMd5(md5)
previewFileCacheService.removeCache(md5, projectId, repoName)
logger.warn("node does not exist, delete the cache information, key:$md5")
null
}
Expand Down
Loading

0 comments on commit f495c1c

Please sign in to comment.