diff --git a/services/service-files/main/default/manager/file.js b/services/service-files/main/default/manager/file.js index 867daa8b9e..701d580b05 100644 --- a/services/service-files/main/default/manager/file.js +++ b/services/service-files/main/default/manager/file.js @@ -97,7 +97,7 @@ class File { const doc = { "_id": _id, - "link": process.env.ROOT_URL+"/api/files/images/"+_id, + "link": process.env.ROOT_URL+`/api/files/${fsCollectionName}/`+_id, "original": { "type": mimetype, "size": size, diff --git a/services/service-files/package.json b/services/service-files/package.json index 9aa1c4237b..71296ae74f 100644 --- a/services/service-files/package.json +++ b/services/service-files/package.json @@ -10,6 +10,7 @@ }, "dependencies": { "aws-sdk": "2.0.23", + "file-type": "16.5.4", "formidable": "2.0.1", "mkdirp": "^1.0.4", "moment": "^2.29.1" diff --git a/services/service-files/package.service.js b/services/service-files/package.service.js index 4d890f3f6d..b98add2319 100644 --- a/services/service-files/package.service.js +++ b/services/service-files/package.service.js @@ -2,7 +2,7 @@ * @Author: sunhaolin@hotoa.com * @Date: 2022-06-08 09:38:56 * @LastEditors: 孙浩林 sunhaolin@steedos.com - * @LastEditTime: 2023-09-09 16:48:46 + * @LastEditTime: 2023-10-07 18:04:23 * @Description: */ "use strict"; @@ -13,6 +13,17 @@ const packageName = project.name; const packageLoader = require('@steedos/service-package-loader'); const Fiber = require('fibers') +const path = require('path') +const os = require('os') +const fs = require('fs') +const hexoid = require('hexoid') +const toHexoId = hexoid(25) +const FileType = require('file-type'); +const { + getCollection, + File, +} = require('./main/default/manager'); + /** * @typedef {import('moleculer').Context} Context Moleculer's Context * 软件包服务启动后也需要抛出事件。 @@ -88,6 +99,76 @@ module.exports = { }).run(); }) } + }, + + /** + * 上传文件,调用示例: + * const stream = fs.createReadStream(filepath); + const fileDoc = await this.broker.call('~packages-@steedos/service-files.uploadCollectionFile', stream, { + meta: { + filename, // 文件名 + owner // 所有者ID + } + }) + */ + uploadCollectionFile: { + async handler(ctx) { + return await new Promise(function (resolve, reject) { + try { + const stream = ctx.params + const { filename, owner } = ctx.meta + // console.log('>'.repeat(20), 'uploadCollectionFile:', filename) + if (!filename || !owner) { + throw new Error('need filename and owner') + } + + // 存成临时文件 + const tempFilename = toHexoId(); + const tempFilepath = path.join(path.resolve(os.tmpdir()), tempFilename) + // console.log(require('chalk').red(tempFilepath)) + const tempWS = fs.createWriteStream(tempFilepath); + stream.pipe(tempWS); + + tempWS.on('finish', async () => { + // console.log('All writes are now complete.'); + const fileStats = fs.statSync(tempFilepath) + + const FS_COLLECTION_NAME = "files"; + const DB_COLLECTION_NAME = `cfs.${FS_COLLECTION_NAME}.filerecord`; + const collection = await getCollection(DB_COLLECTION_NAME); + + const mimeInfo = await FileType.fromFile(tempFilepath) + const mimetype = mimeInfo.mime + const newFile = new File({ + name: filename, + size: fileStats.size, + mimetype, + fsCollectionName: FS_COLLECTION_NAME + }); + + newFile.metadata = { + owner + }; + // 保存文件 + newFile.save(tempFilepath, async function (err, result) { + if (err) { + reject(err) + return; + } + + await collection.insertOne(newFile.insertDoc()); + + const fileDoc = await collection.findOne({ _id: newFile.id }); + resolve(fileDoc); + }) + }); + + + } catch (error) { + reject(error); + } + }) + } } }, diff --git a/services/service-plugin-amis/public/tailwind/tailwind-steedos.css b/services/service-plugin-amis/public/tailwind/tailwind-steedos.css index ec022a0320..7df8e344dc 100644 --- a/services/service-plugin-amis/public/tailwind/tailwind-steedos.css +++ b/services/service-plugin-amis/public/tailwind/tailwind-steedos.css @@ -54,6 +54,10 @@ position: absolute } +.relative { + position: relative +} + .sticky { position: sticky } @@ -65,6 +69,10 @@ left: 0px } +.isolate { + isolation: isolate +} + .z-20 { z-index: 20 } diff --git a/yarn.lock b/yarn.lock index 19f7e769ca..e3d2878909 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3685,6 +3685,11 @@ request "^2.88.0" webfinger "^0.4.2" +"@tokenizer/token@^0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@tokenizer/token/-/token-0.3.0.tgz#fe98a93fe789247e998c75e74e9c7c63217aa276" + integrity sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A== + "@tootallnate/once@1": version "1.1.2" resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" @@ -8779,6 +8784,15 @@ figures@^3.0.0: dependencies: escape-string-regexp "^1.0.5" +file-type@16.5.4: + version "16.5.4" + resolved "https://registry.yarnpkg.com/file-type/-/file-type-16.5.4.tgz#474fb4f704bee427681f98dd390058a172a6c2fd" + integrity sha512-/yFHK0aGjFEgDJjEKP0pWCplsPFPhwyfwevf/pVxiN0tmE4L9LmwWxWukdJSHdoCli4VgQLehjJtwQBnqmsKcw== + dependencies: + readable-web-to-node-stream "^3.0.0" + strtok3 "^6.2.4" + token-types "^4.1.1" + file-uri-to-path@2: version "2.0.0" resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-2.0.0.tgz#7b415aeba227d575851e0a5b0c640d7656403fba" @@ -14797,6 +14811,11 @@ pbkdf2@^3.0.3: safe-buffer "^5.0.1" sha.js "^2.4.8" +peek-readable@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/peek-readable/-/peek-readable-4.1.0.tgz#4ece1111bf5c2ad8867c314c81356847e8a62e72" + integrity sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg== + pegjs@^0.10.0: version "0.10.0" resolved "https://registry.yarnpkg.com/pegjs/-/pegjs-0.10.0.tgz#cf8bafae6eddff4b5a7efb185269eaaf4610ddbd" @@ -15834,6 +15853,13 @@ readable-stream@~2.1.5: string_decoder "~0.10.x" util-deprecate "~1.0.1" +readable-web-to-node-stream@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz#5d52bb5df7b54861fd48d015e93a2cb87b3ee0bb" + integrity sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw== + dependencies: + readable-stream "^3.6.0" + readdir-glob@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/readdir-glob/-/readdir-glob-1.1.2.tgz#b185789b8e6a43491635b6953295c5c5e3fd224c" @@ -17409,6 +17435,14 @@ strong-log-transformer@^2.1.0: minimist "^1.2.0" through "^2.3.4" +strtok3@^6.2.4: + version "6.3.0" + resolved "https://registry.yarnpkg.com/strtok3/-/strtok3-6.3.0.tgz#358b80ffe6d5d5620e19a073aa78ce947a90f9a0" + integrity sha512-fZtbhtvI9I48xDSywd/somNqgUHl2L2cstmXCCif0itOf96jeW18MBSyrLuNicYQVkvpOxkZtkzujiTJ9LW5Jw== + dependencies: + "@tokenizer/token" "^0.3.0" + peek-readable "^4.1.0" + subscriptions-transport-ws@^0.9.18, subscriptions-transport-ws@^0.9.19: version "0.9.19" resolved "https://registry.yarnpkg.com/subscriptions-transport-ws/-/subscriptions-transport-ws-0.9.19.tgz#10ca32f7e291d5ee8eb728b9c02e43c52606cdcf" @@ -17868,6 +17902,14 @@ token-stream@1.0.0: resolved "https://registry.yarnpkg.com/token-stream/-/token-stream-1.0.0.tgz#cc200eab2613f4166d27ff9afc7ca56d49df6eb4" integrity sha512-VSsyNPPW74RpHwR8Fc21uubwHY7wMDeJLys2IX5zJNih+OnAnaifKHo+1LHT7DAdloQ7apeaaWg8l7qnf/TnEg== +token-types@^4.1.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/token-types/-/token-types-4.2.1.tgz#0f897f03665846982806e138977dbe72d44df753" + integrity sha512-6udB24Q737UD/SDsKAHI9FCRP7Bqc9D/MQUV02ORQg5iskjtLJlZJNdN4kKtcdtwCeWIwIHDGaUsTsCCAa8sFQ== + dependencies: + "@tokenizer/token" "^0.3.0" + ieee754 "^1.2.1" + touch@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/touch/-/touch-3.1.0.tgz#fe365f5f75ec9ed4e56825e0bb76d24ab74af83b"