# @fs/attachment 文件中心服务 ## 一、Synopsis 文件中心提供文件的 `上传/下载/删除` 服务,支持云存储和本地存储。 ### 存储形式 - 云存储:基于七牛云服务实现的文件服务 - 本地存储:本地磁盘 ### 服务形式 - 原生 API 服务:应用侧直接引用 npm 包,调用 API 编程接口 - REST API 服务:使用 `fs-web-server-scaffold` 脚手架,该服务以中间件形式提供 ## 二、Installation ### Node.js @fs/attachment is available on npm. To install it, type: `npm install @fs/attachment` ## 三、Usage ### Native API 服务 ```js const Attachment = require('@fs/attachment'); const opts = { qiniu: { // 可选 accessKey: 'your access key', secretKey: 'your secret key', bucket: 'bucket', domain: 'bucket domain' }, local: { // 不指定七牛云配置,默认使用本地存储服务 origin: 'your local storage server origin', // 必填 rootPath: 'static', childPath: 'upload' }, uploadPath: 'your path', maxSize: 10485760 // 10M }; const attachment = new Attachment(opts); let rslt = attachment.upload(file); // let rslt = attachment.upload(file, {uploadPath: 'report'}); // 文件上传路径自定义为“report”,这里的 uploadPath 优先级高于 opts.uploadPath attachment.download(rslt.key); attachment.remove(rslt.key); ``` ### REST API 服务 #### 1. REST API ##### 接口定义 ```js let prefix = opts.routePrefix ? `/${opts.routePrefix}` : ''; /** * @api {POST} /attachments/:p 上传文件. * @apiVersion 1.0.0 * @apiGroup Attachment */ router.post(`${prefix}/attachments/:p`, attachment.upload(mw)); /** * @api {GET} /attachments 下载文件. * @apiVersion 1.0.0 * @apiGroup Attachment */ router.get(`${prefix}/attachments`, attachment.download(mw)); /** * @api {DELETE} /attachments 删除文件. * @apiVersion 1.0.0 * @apiGroup Attachment */ router.del(`${prefix}/attachments`, attachment.deletee(mw)); /** * @api {POST} /attachments 批量删除文件. * @apiVersion 1.0.0 * @apiGroup Attachment */ router.post(`${prefix}/attachments`, attachment.bulkDelete(mw)); ``` ##### 接口说明 ###### 上传指定文件 **HTTP Request** ``` POST /attachments/:p ``` **URL Parameters** | 参数 | 类型 | 默认值 | 必填 | 说明 | | ---- | ------ | ------ | ---- | ---------------- | | p | string | other | 是 | 文件存放的文件夹 | **Body Parameters** ``` form-data ``` **Response 200** ```json { "uploaded": "upload/report/WuSongQiao_daily_20181112_b46278f0-58cc-4dd7-9295-8021a57c86da.xls", "key": "upload/report/WuSongQiao_daily_20181112_b46278f0-58cc-4dd7-9295-8021a57c86da.xls", "url": "http://localhost:8081/upload/report/WuSongQiao_daily_20181112_b46278f0-58cc-4dd7-9295-8021a57c86da.xls" } ``` ###### 下载指定文件 **HTTP Request** ``` GET /attachments ``` **Query Parameters** | 参数 | 类型 | 默认值 | 必填 | 说明 | | -------- | ------ | ------ | ---- | --------------------------------------- | | src | string | -- | 是 | 文件 key 值,如:upload/data/report.xls | | filename | string | -- | 是 | 保存的文件名,如:myreport.xls | **Response 200** ```json 文件数据 ``` ###### 删除指定文件 **HTTP Request** ``` DELETE /attachments ``` **Query Parameters** | 参数 | 类型 | 默认值 | 必填 | 说明 | | ---- | ------ | ------ | ---- | --------------------------------------- | | src | string | -- | 是 | 文件 key 值,如:upload/data/report.xls | **Response 204** ###### 批量删除文件 **HTTP Request** ``` POST /attachments ``` **Body Parameters** | 参数 | 类型 | 默认值 | 必填 | 说明 | | ---- | --------------- | ------ | ---- | ------------------------------------------------------------ | | srcs | array of string | -- | 是 | 文件 key 值数组,如:["upload/data/吴淞桥_日报表_2018年11月12日_d2af9cf7-ea87-4d5f-a74a-1ebbaf37e307.xls", "upload/data/HongGu_daily_2021_a0292f7d-d97c-4a32-a148-10c70ea8e032.xls"] | **Response 200** ```json { "keys": [ "upload/data/吴淞桥_日报表_2018年11月12日_d2af9cf7-ea87-4d5f-a74a-1ebbaf37e307.xls", "upload/data/HongGu_daily_2021_a0292f7d-d97c-4a32-a148-10c70ea8e032.xls" ] } ``` #### 2. fs-web-server-scaffold 配置示例 ```js /** * Created by Julin on 2021/04/02. */ 'use strict'; const path = require('path'); const os = require('os'); const dev = process.env.NODE_ENV == 'development'; const ANXINCLOUD_FC_CLOUD = process.env.ANXINCLOUD_FC_CLOUD; const ANXINCLOUD_FC_LOCAL_SVR_ORIGIN = process.env.ANXINCLOUD_FC_LOCAL_SVR_ORIGIN; const ANXINCLOUD_FC_LOCAL_ROOT_PATH = process.env.ANXINCLOUD_FC_LOCAL_ROOT_PATH; const PORT = 4000; const product = { port: PORT, staticDirs: [path.join(__dirname, ANXINCLOUD_FC_LOCAL_ROOT_PATH || 'static')], mws: [{ entry: require('@fs/attachment').entry, opts: Object.assign({ routePrefix: '_file-server', uploadPath: 'other', maxSize: 10485760 // 10M }, ANXINCLOUD_FC_CLOUD == 'true' ? { qiniu: { domain: 'http://p7q1f8t1p.bkt.clouddn.com', bucket: 'anxinyun-test', accessKey: "5XrM4wEB9YU6RQwT64sPzzE6cYFKZgssdP5Kj3uu", secretKey: "w6j2ixR_i-aelc6I7S3HotKIX-ukMzcKmDfH6-M5" } } : { local: { origin: ANXINCLOUD_FC_LOCAL_SVR_ORIGIN || `localhost:${PORT}`, rootPath: 'static', childPath: 'upload' } }) }], dc: { url: 'postgres://FashionAdmin:123456@10.8.30.39:5432/axy', opts: { pool: { max: 20, min: 10, idle: 10000 }, define: { freezeTableName: true, // 固定表名 timestamps: false // 不含列 "createAt"/"updateAt"/"DeleteAt" }, timezone: '+08:00', logging: false }, models: [] }, logger: { level: 'info', json: false, filename: path.join(__dirname, 'log', 'runtime.test.log'), colorize: false, maxsize: 1024 * 1024 * 5, rotationFormat: false, zippedArchive: true, maxFiles: 10, prettyPrint: true, label: '', timestamp: true, eol: os.EOL, tailable: true, depth: null, showLevel: true, maxRetries: 1 } }; const development = { port: product.port, mws: product.mws, dc: product.dc, logger: product.logger }; if (dev) { // logger development.logger.filename = path.join(__dirname, 'log', 'development.test.log'); development.logger.level = 'debug'; development.dc.opts.logging = console.log; } module.exports = dev ? development : product; ```