工作中遇到的一个问题, 这里简单记录下解决过程.
起因是后台频现用户上传了违规图片, 收到了七牛的警告邮件. 老大要求搭建一个nsfw(Not-Safe-For-Work)服务, 在图片上传到七牛云存储前, 先调用这个服务, 确定图片没有违规, 再上传.
搭建服务
找到了全网star最多的一个开源项目 nsfwjs, 文档中给到了一个完整的 Express 的例子. 照着来就好.
参考 Express Docs 官方文档, 使用express-generator 快速搭个架子, 将 nsfwjs 文档中给到的server.js 部分的示例代码放进去. 本地起服务 node server.js
, 使用 curl 测试, 结果符合预期:
curl --request POST localhost:8080/nsfw --header 'Content-Type: multipart/form-data' --data-binary 'image=@/full/path/to/picture.jpg'
支持多格式
nsfwjs 给到的例子中, 只支持JPEG格式的文件, 改用 image-decode 换掉 jpeg-js. 可支持jpeg, jpg, png, gif, bmp, tiff, webp 格式的图片, 基本满足需求.
yarn remove jpeg-js
yarn add image-decode
修改 convert 部分的代码如下:
const decode = require('image-decode')
......
const convert = async (img) => {
const { data, width, height } = decode(img)
const numChannels = 3
const numPixels = width * height
const values = new Int32Array(numPixels * numChannels)
for (let i = 0; i < numPixels; i++)
for (let c = 0; c < numChannels; ++c)
values[i * numChannels + c] = data[i * 4 + c]
return tf.tensor3d(values, [height, width, numChannels], 'int32')
}
CROS 配置
在本地起了 Vue 的一个项目, 在这个 Vue 项目中, 使用 axios 给 nsfw 项目发请求的时候, 会出现 CROS 的报错.
当时直接 Google, StackOverflow 上一堆提到全局设置 header 的, 试了下, 结果无效, 踩了点坑…. 其实直接使用 cors 就能简单粗暴地解决:
yarn add cors
修改 server.js:
var cors = require('cors');
......
var app = express();
......
// cors settings
var corsOptionsDelegate = function (req, callback) {
const corsOptions = { origin: true, credentials: true }
callback(null, corsOptions)
}
app.use(cors(corsOptionsDelegate));
......
这里设置了{ origin: true, credentials: true }
, cors 的文档中, 默认配置中 origin 为 *, credentials 未设置.
直接使用默认配置会报错:
Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'
干脆直接都设置成true.
再次使用 axios 发送请求, OK.