使用nginx模仿S3做文件上传下载限制的简单实现

背景:公司产品的文件管理本来是使用AWS的S3文件存储服务的,优点主要就是给用户上传下载的链接都是用的S3的PreSignedUrl, 可以提供一定时限内的文件访问权限,过了时限后链接就失效需要重新获取。但是现在在做一个项目不能使用S3,所以需要用其他方法来模拟这个权限操作;

 

需要实现以下几个API:

1.当用户请求上传的时候,发给用户一个地址,允许用户对着这个地址使用put请求传递binary的文件,该地址要在一定时间后失效

2.当用户根据文件名请求文件真实地址的时候,返回一个地址,这个地址可以直接在浏览器里面打开下载或查看(图片等),该地址要在一定时间后失效

3.Java模拟S3自己api的upload,download等操作

 

实现概述:

0、文件存放在nginx的目录里;

1、文件的上传是通过Java写的API来实现的;

2、文件的下载是直接访问nginx服务的URI实现的;

3、用户的上传和下载都要经过nginx并拦截非法超时请求;

4、Java模拟S3自己api的upload,download等操作实际就是Linux服务器内部的文件复制

 

代码:

1.文件上传API:

@RequestMapping(value = "default/{path}/{name:.+}", method = RequestMethod.PUT)
    public void put(HttpServletRequest request,
                    @PathVariable(value = "path") String folder,
                    @PathVariable(value = "name") String fileName) throws Exception {

        try {
            InputStream inputStream = request.getInputStream();

            if (inputStream != null) {
                String filePath = ROOTPATH + folder + File.separator + fileName;
                FileOutputStream outputStream = new FileOutputStream(new File(filePath));

                byte[] buffer = new byte[1024];
                int bytesRead;

                while ((bytesRead = inputStream.read(buffer)) > 0) {
                    outputStream.write(buffer, 0, bytesRead);
                }

                outputStream.flush();

            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

这个初步给到用户的上传地址就是 http://localhost/default/upload/filename.txt

API会自动解析

目录 upload/

文件名 filename.txt

然后放在Linux本地的对应路径下面去

 

2.文件的下载是直接访问nginx服务的URI实现的;这一步没什么好说的,就是直接访问文件http://localhost/default/upload/filename.txt

 

3.用户的上传和下载都要经过nginx并拦截非法超时请求;这一步是本文核心,Java的API需要先设置经过nginx反向代理转发

主要在以下几个地方加点拦截:

a.给用户上传的地址的时候不能直接给,扩展上面的http://localhost/default/upload/filename.txt,拦截后输出给用户的是

http://localhost/default/upload/filename.txt?auth=1558092039000

其中的auth参数是当前时间戳。然后写一个空文件,命名为filename.txt-1558092039000,找个nginx可以访问到的路径存放

b.给用户下载的地址同上

c.当用户来访问http://localhost/default/upload/filename.txt?auth=1558092039000的时候,会先通过nginx,在nginx里做如下配置:

#在server的外面(上面),这里主要是取到链接里的文件名
map $uri $basename {
    ~/(?<captured_basename>[^/]*)$ $captured_basename;
}
#在server的里面
set $auth_cache "auth_cache";
location /attachment/ {
        if ($arg_auth = '') {
                return 401;
        }
        if (!-f $document_root/$auth_cache/$basename-$arg_auth) {
                return 401;
         }
}

我这里是把空文件filename.txt-1558092039000放在了 nginx根目录的  /auth_cache/filename.txt-1558092039000,然后当用户来访问的时候,取用户访问的文件名和时间戳,然后去看看这个文件是否存在,如果存在的话说明是授权过的,就通过,不然就直接返回401

d.写个定时任务或者脚本,每隔一段时间去检查一遍/auth_cache/里面的文件,看那些时间戳超过了2个小时,就把这个空文件删掉,这样链接就失效了

4.略

 

 

本文中间可能省略的步骤比较多,所以有些参数名不能完整的对应。但是核心思想就是以一个空文件作为用户每次链接访问的认证。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值