@isoftdata/file-service
v7.0.2
Published
A generic files service for any ISoft platform.
Maintainers
Keywords
Readme
Project Background
This project can be using in an existing app that has an Express backend file server or it can act as a standalone file server. It's designed for use with standard ISoft-style-application MYSQL schema(SELECTs from file and filechunk tables).
Installing
npm i @isoftdata/file-service
Getting Started
This project is designed with two use cases in mind:
For Use in a Project with an Existing Web Server
API
@isoftdata/file-service exports an object with a registerFileServiceRoute function on it. That function takes the an object with the following shape:
Name | Type | Description | Default Value
---- | ---- | ----------- | -------------
webServer | Object | Must be an express server instance | N/A - Prop is Required
connection | Object | Must be one of mysql's Pool, Connection, or PoolConnection classes | N/A - Prop is Required
routePrefix | String | The HTTP route from which the image(s) will be served | /**
connectionTip: if you give aPoolclass for theconnection, a single connection will be pulled from the pool for each individual request and released at the end of that request. The connection won't be released if you pass aPoolConnectionorConnection(of course).
routePrefixTip: if you want to serve images from the root of the web server, give an empty string forroutePrefix.
Example usage:
import express from 'express'
import fileUpload from 'express-fileupload'
import mysql from 'mysql'
import { registerFileServiceRoute } from '@isoftdata/file-service'
const expressServer = express()
const port = process.env.PORT ?? 80
const pool = mysql.createPool({
host: 'example.org',
user: 'bob',
password: 'secret',
database: 'my_db',
})
// This will enable file upload support for the express server.
expressServer.use(fileUpload())
// This adds the `/file` and `/upload` routes to the express server.
registerFileServiceRoute({ webServer: expressServer, connection: pool })
// Start the server
expressServer.listen({ port }, () => console.log(`🚀 Server ready on port ${port}!`))As a Standalone Web Server
- Clone this repository
- Run
npm i - Create a
.envfile in the root of the project that looks like this, but with valid values filled out:
MYSQL_HOST=
MYSQL_USER=
MYSQL_PASSWORD=
MYSQL_DATABASE=
PORT=- Run
npm run start
The web server will accept requests to any path so long as the path ends in
<md5-checksum-of-the-file><file-id>/<file-name>.
In other words,
foo/bar/baz/fd90a7512022dd825fcd41982ec466931956/mySweetPicture.jpgis just as valid and the same asimages/fd90a7512022dd825fcd41982ec466931956/mySweetPicture.jpg.
Request Parameters
When making a request for an image, a few GET parameters are available(all optional):
widthheightbackground(defaults to255)fit
These parameters, if valid, are passed into the Sharp image processor. For details on these parameters, check out the Sharp resize docs.
Using the Client
The FileServiceClient class is exported by this module and can be used to upload images. Example usage:
import { FileServiceClient } from '@isoftdata/file-service'
import fs from "fs"
const client = new FileServiceClient({
maxImageHeight: 1024, // optional
maxImageWidth: 1024, // optional
url: 'http://localhost:4000', // wherever the service is
})
client.addFile({
name: 'myFile.jpg', // optional
stream: fs.createReadStream('./myFile.jpg'),
})
client.addFile({
// If name is omitted, the express file upload middleware will give it a name.
stream: anyReadableStream,
})
// This will upload all the files that have been added above. It will return a Promise<UploadResult[]>
const resultsPromise = client.upload()What about authentication?
The file service doesn't have any concept or opinions about authentication requirements baked in. If you want to ensure that your files can't be accessed by someone that could guess the MD5 hash + fileid combo, we recommend you write an authentication checking middleware function that you register before the file service. Something like this:
import express from 'express'
import cookieParser from 'cookie-parser'
const app = express()
expressServer.use(cookieParser())
expressServer.use('/files', async(req, res, next) => {
const authenticated = await isAuthenticated(req.cookies.token)
if(!authenticated) {
next(new Error('Not Authenticated'))
} else {
next()
}
})where the isAuthenticated function is from your app and knows how to check if a session is valid/authenticated.
What schema is required?
Some common ISoft schema is expected:
Tables:
filefilechunk
Functions:
f_get_attachment_data
Breaking changes
Version 3
The only breaking change from version 2 to 3 was the requirement of Node 16
Version 4
Removed opinion of the File service that only images can be uploaded using the imported File Service functions. *Chunker chunks files properly
Version 5
Updated from CJS to ESM
Version 6
Supports MySQL and MySQL2 through the abstraction layer of the @isoftdata/utility-db pool/connection wrappers.
Supports/requires/uses Node 20 in Docker builds and therefore requires Ubuntu 20 or higher on the host OS.
Version 7
Drops support for Node versions < 20.6.0 and drops dotenv dependency in favor of native process.loadEnvFile and the --env-file-if-exists CLI flag.
