wo-base-fileloader/fileloader.js
2023-03-13 01:32:13 +08:00

56 lines
3.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const multer = require('multer')
const path = require('path')
const crypto = require('crypto')
const wo = global.wo
module.exports = {
MulterStore: multer({
// dest:'./File/', // 这样,不能自定义文件名。
storage: multer.diskStorage({
destination (req, file, cb) {
// 如果直接提供字符串multer会负责创建该目录。如果提供函数你要负责确保该目录存在。
cb(null, wo?.envar?.fileStore) // 目录是相对于本应用的入口js的即相对于 server.js 的位置。
},
filename (req, file, cb) {
// file 为 {encoding, fieldname, mimetype, originalname, stream}
// 注意req.body 也许还没有信息因为这取决于客户端发送body和file的顺序。必要的信息请从 req.headers 传递,例如 _passtoken在multer时尚未进入路由不存在已装好的 _passtokenSource
// 虽然可以把本方法写成 async 的,并且在这里调用 wo.ipfsStore.ipfs.add(file.stream) 来获取 cid但是最后在本地存成的文件是 0字节的。因此还是用个随机数吧。
// 或者,干脆利用这个缺陷,直接提交到 ipfs在本地就留着0字节文件不要使用就好了。同时在 api.receiveFile 里,就要相应的直接返回 IPFS 网址给前端。
const filename = `${Date.now()}-${crypto.randomBytes(16).toString('hex')}${path.extname(file.originalname)}`
//const _passtokenSource = webtoken.verifyToken(req.headers._passtoken) || {}
//const filename = `${req.path.replace(/^\/api\d*/, '')}_${_passtokenSource.usid}_${Date.now()}${fileNameExtension}` // 如果最终 filename 含有 / (例如当 req.path 为 Who/todo则必须已经存在该目录否则在这里就出错不会进入下面流程。
cb(null, filename)
},
}),
// fileFilter:function(req, file, cb) {},
limits: { fileSize: 10485760 },
}).single('file'),
api: {
async receiveFile () {
// req 被 multer 处理后req.file 为 { destination, filename, originialname, path, mimetype, size }, 其中 path 包括了 destination 和 filename 的文件相对路径。
const file = wo._req?.file
if (file?.path) {
file.path = file.path.replace('\\', '/')
if (wo?.ipfsStore) {
// 为了在这里使用 wo.ipfsStore.add, 需要提供 FileContent不能直接用 req.file
// 20230312: not working with nodejs above (not including) 18.2.1! https://github.com/nodejs/node/issues/46221
const { cid } = await wo.ipfsStore.add(wo.ipfsLib.globSource(file.path), {
cidVersion: 1,
hashAlg: 'sha2-256',
onlyHash: false, // 多个备份是好的,而且能加快下次添加同样文件的速度。
pin: false,
})
file.cid = cid?.toString() // + path.extname(file.filename)
file.ipfsUrl = wo.envar.ipfsGateway + file.cid
// file.path = wo.envar.ipfsGateway + file.cid // 可选考虑直接返回 ipfs地址。在本地测试成功但是发现第一次上传的文件作为ipfs网关图片在前端显示比较慢不如显示http的快。第二次上传同样文件的ipfs前端显示就快了。
}
return { _state: 'SUCCESS', ...file }
} else {
return { _state: 'WOBASE_FAIL_FILE_NOT_RECEIVED' }
}
},
},
}