[实训日志]四、Nginx配置、文件上传模块nginx-upload-module安装使用、带权限验证的视频获取

一、nginx和上传模块的的安装

  下载nginx和nginx-upload-module的gz包后进行解压,使用

./configure --prefix=/usr/local/nginx --add-module=../nginx-upload-module-2.3.0
命令添加模块,但是提示需要ssl库。

[实训日志]四、Nginx配置、文件上传模块nginx-upload-module安装使用、带权限验证的视频获取_第1张图片

在ubuntu下执行以下命令安装opssl的开发库,再次执行configure就没有报错了。

最后执行make和make install命令完成安装。

二、nginx配置


worker_processes  20;

error_log  logs/error.log notice;

working_directory /usr/local/nginx;

user root;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    server {
        listen       80;
        client_max_body_size 100m;
        #图片
        location ~ (/user/curuser/image)|(/teachers/curTeacher/course/.*/image) {
            upload_pass   @test;
            upload_store static/images/ ;
            upload_store_access user:r;
            # upload_set_form_field "${upload_field_name}_name" $upload_file_name;
            upload_set_form_field "${upload_field_name}_content_type" $upload_content_type;
            upload_set_form_field "${upload_field_name}_path" $upload_tmp_path;
            upload_aggregate_form_field "${upload_field_name}_md5" $upload_file_md5;
            upload_aggregate_form_field "${upload_field_name}_size" $upload_file_size;
            upload_pass_form_field "^.*$";
            upload_cleanup 400 403 404 499 500-505;
        }
        #视频
        location ~ /teachers/curTeacher/course/.*/chapter/.*/video {
            upload_pass   @test;
            upload_store static/videos/ ;
            upload_store_access user:r;
            # upload_set_form_field "${upload_field_name}_name" $upload_file_name;
            upload_set_form_field "${upload_field_name}_content_type" $upload_content_type;
            upload_set_form_field "${upload_field_name}_path" $upload_tmp_path;
            upload_aggregate_form_field "${upload_field_name}_md5" $upload_file_md5;
            upload_aggregate_form_field "${upload_field_name}_size" $upload_file_size;
            upload_pass_form_field "^.*$";
            upload_cleanup 400 403 404 499 500-505;
        }
        
        location @test {
            proxy_pass   http://192.168.205.1:8091;
        }

        location / {
        	proxy_pass  http://192.168.205.1:8091;
        }
        location /images {
        	root static;
        }
        location /videos {
        	internal;
        	root static;
        }

        location ~ /course/.*/chapter/.*/video {
        	proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Nginx-Proxy true;
            proxy_set_header Connection "";
            proxy_pass http://192.168.205.1:8091;
        }
        
    }
}

上传的图片统一放在static里的images文件夹下。

三、后台

(一)上传文件后台

  由于文件被nginx从请求体中分离,并且把文件在nginx服务器里的路径发送给了后端,因此后端拿到url后可以直接保存在数据库中。这里的url是在linux的绝对路径,需要自己写个函数把它变成相对路径。

@PostMapping("/user/curuser/image")
    @ResponseBody
    public CommonResponse uploadUserHeadImg(@RequestParam("userImageFile_path") String url) {
        UserModel userModel = new UserModel();
        userModel.setUserId(ShiroUtils.getCurUserId());
        userModel.setHeadUrl(getRealUrl("images", url));
        userService.updateUserById(userModel);
        return ResponseUtils.getOKResponse();
    }

(二)视频文件获取权限验证

//获取章节视频
    @RequestMapping("/course/{courseId}/chapter/{chapterId}/video")
    public void getChapterVideoHeader(@PathVariable("courseId") Integer courseId,
                                                @PathVariable("chapterId") Integer chapterId,HttpServletRequest request, HttpServletResponse response) {
        String chapterVideoUrl = userService.getChapterVideoUrl(ShiroUtils.getCurUserId(), courseId, chapterId);
        response.setHeader("Content-Type", "application/octet-stream");
        response.setHeader("X-Accel-Redirect", "/" + chapterVideoUrl);//通过这个响应头让nginx在内部获取对应的视频文件
        response.setHeader("X-Accel-Charset", "utf-8");
        response.setHeader("Content-Disposition", "attachment; filename=" + chapterVideoUrl);
        response.setHeader("Cache-Control", "no-store"); //禁止浏览器缓存 这个可以用在试看视频上  完整视频可以缓存
    }

四、异常处理

  由于用户是先上传文件,然后请求才被发到后端服务器,如果权限认证失败或者服务器入库失败,nginx应该把刚才的图片删除。上面配置文件里upload_cleanup 命令指定了后端返回什么状态码时会把文件删除,因此后端发生异常后应该返回错误码。但是由于我使用前后端分离架构,所有错误都会返回200,然后在json里描述错误原因,因此需要再定义一个异常,对这个异常返回403状态码让nginx删除图片。

 UploadAdvice.java    使用AOP进行异常捕获并且转换成UploadException

@Aspect
@Component
public class UploadAdvice {
    @Pointcut("execution(public  * org.darod.elearning.gateway.controller.UploadImageController.*(..))")
    void uploadMethod() {}
    @AfterThrowing(pointcut = "uploadMethod()", throwing = "ex")
    public void doUploadMethodException(Throwable ex) {
        if(ex instanceof BusinessException){
            BusinessException businessException = (BusinessException) ex;
            throw new UploadException(businessException);
        }else
            throw new UploadException(EmException.UNKNOWN_ERROR,"文件上传失败");
    }
}

然后在全局异常捕获中新增对UploadException的处理,让它返回403状态码。

 @ExceptionHandler(UploadException.class)
    @ResponseStatus(HttpStatus.FORBIDDEN)
    @ResponseBody
    public CommonResponse handlerUploadException(HttpServletRequest request, Exception exception) {
        Map map = new HashMap<>();
        if (exception instanceof UploadException) {
            BusinessException businessException = (BusinessException) exception;
            map.put("errCode", businessException.getErrCode());
            map.put("errMsg", businessException.getErrMsg());
        }
        return ResponseUtils.getErrorResponse(map);
    }

 

你可能感兴趣的:(实训记录)