这里写目录标题
springboot创建文件无法读取问题
@PostMapping(value = "/upload/pic")
@Operation(summary = "上传图片", description = "上传图片接口")
public R<AttachmentVo> uploadPic(MultipartFile file) {
String dir = DateUtils.dateTime();
File folder = new File(filePath + "/pic/" + dir);
if (!folder.isDirectory()) {
if (!folder.mkdirs()) {
return R.fail(ErrorCode.ERROR_SYSTEM);
}
}
String oldName = file.getOriginalFilename();
String ext = oldName.substring(oldName.lastIndexOf(".")).toLowerCase();
if (!imgExt.contains(ext)) {
return R.fail(ErrorCode.ERROR_UPLOAD.getCode(), "仅支持上传jpg、png图片");
}
//生成后缀
String fileName = SequenceUtil.getSequenceNumber()+ ext;
try {
file.transferTo(new File(folder, fileName));
AttachmentVo attachmentVo = new AttachmentVo();
attachmentVo.setName(oldName);
attachmentVo.setUrl(host + "/pic/" + dir + "/" + fileName);
return R.ok(attachmentVo);
} catch (Exception e) {
e.printStackTrace();
return R.fail(ErrorCode.ERROR_SYSTEM);
}
}
nginx# error.log
[error] 53942#0: *11 open() “/data/wwwroot/static.ltkj.com/pic/20230804/530804180800118102.jpg” failed (13: Permission denied)
问题描述
通过springboot创建出来的项目,在项目里会有将文件存储到后端服务器的动作,文件存储后默认的权限是rw--------- root root 也就是说除了root具有读写的权限,其他所有用户都没有任何权限。现在想要做个文件预览功能,就需要对他进行可读。
问题解决思路
既然问题出现在创建的权限之上,首先想到的就是解决权限问题,将文件的创建权限改成rw-r-r即可。
问题解决过程
- 根据上面问题的解决思路首先去配置了/etc/bash.bashrc文件,在该文件末尾加了umask 0022(这样修改理论上所有用户创建的文件权限都是644,也就是rw-r-r),然后重新加载该文件 source /etc/bash.bashrc之后,登录服务器验证权限修改是否生效:在目录下创建了个文件,发现权限确实对了,然后登录系统使用系统进行上传文件,然后发现应用创建出来的文件权限还是没变,仍然是rw
- 此时感觉是有另外一个地方限制了这个权限,网络上搜索一通后发现一种说法tomcat的配置文件catalina.sh会对创建文件进行权限默认值的设定,这里默认设定就是只有rw----。此时感觉发现了问题的关键处,但是springboot的tomcat都是内置的,并没有catalina.sh这个文件。这可怎么整,然后找了一通发现这个并没有办法在springboot中进行设定,这条问题解决线路到这里就断了(若不是内置tomcat这个问题就很好解决,只需要找到catalina.sh中设定的umask值,进行更改成0022即可)。
- 上面没有成功解决问题,就只能更换思路了,默认创建出来的文件权限是rw------- root root ,那root用户是具有读写权限的,我若是将访问文件的用户设置成 root,这个问题解决也是ok的,下面就朝着这个反向进行重新努力。
- 经过一通搜索发现nginx确实支持这个,只需要我们在nginx.conf开头加入一个配置即可
user root;这样通过nginx反向代理出来的静态资源,我们访问时默认都是使用root进行访问的,此时访问文件就有了读写的权限。这样问题就解决了。
总结
这个问题一开始其实解决就有两个角度:
- 更改文件创建时的默认权限
- 更改访问静态资源时的默认用户
- 在java 程序里修改linux 文件权限
一开始只想到了第一种解决思路,一直在第一条路上深入找解决办法,到最后发现走入了死胡同,才转而想到了第二种。
其实问题思考的初始阶段就应该建立好问题的整体思路,多方向进行思考,这样就可以在一条路上受阻后,在另外一条路上继续寻找解决方案。
二、下面再次尝试第一种方法 改tomcat 或改jdk umask 022
修改linux上的tomcat上的文件权限
打开bin/catalina.sh文件,没有修改过的话大概在263行左右。
将0027改改为0022,重启tomcat,问题解决。
第一步:找到源码位置
第二步:修改文件权限
# Set UMASK unless it has been overridden
if [ -z "$UMASK" ]; then
UMASK="0022"
fi
第三步:重启tomcat即可
sh shutdown.sh(关闭)
sh startup.sh 或者 ./startup.sh(启动)
————————————————
第四步: 但是项目里用的是 springboot 内嵌tomcat, 怎么修改 :
然后看了一下Tomcat启动命令里面有一个参数:
-Dorg.apache.catalina.security.SecurityListener.UMASK=0027
再看了一下catalina.sh文件:
#Set UMASK unless it has been overridden
if [ -z “$UMASK” ]; then
UMASK=“0027”
fi
umask $UMASK
把0027修改为0022就OK了。
第五步: 蜂鸟focus小程序部署是下面这样的 ,没看懂:待研究
[root@iZ2ze6m4la2xm5wzpt7126Z ]$ps -ef |grep java
root 220923 1 0 2022 ? 00:00:00 jsvc.exec -java-home /usr/java/jdk1.8.0_121 -user www -pidfile /www/server/tomcat8/logs/catalina-daemon.pid -wait 10 -umask 0027 -outfile /www/server/tomcat8/logs/catalina-daemon.out -errfile &1 -classpath /www/server/tomcat8/bin/bootstrap.jar:/www/server/tomcat8/bin/commons-daemon.jar:/www/server/tomcat8/bin/tomcat-juli.jar -Djava.util.logging.config.file=/www/server/tomcat8/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Dignore.endorsed.dirs= -Dcatalina.base=/www/server/tomcat8 -Dcatalina.home=/www/server/tomcat8 -Djava.io.tmpdir=/www/server/tomcat8/temp org.apache.catalina.startup.Bootstrap
www 220924 220923 0 2022 ? 04:36:39 jsvc.exec -java-home /usr/java/jdk1.8.0_121 -user www -pidfile /www/server/tomcat8/logs/catalina-daemon.pid -wait 10 -umask 0027 -outfile /www/server/tomcat8/logs/catalina-daemon.out -errfile &1 -classpath /www/server/tomcat8/bin/bootstrap.jar:/www/server/tomcat8/bin/commons-daemon.jar:/www/server/tomcat8/bin/tomcat-juli.jar -Djava.util.logging.config.file=/www/server/tomcat8/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Dignore.endorsed.dirs= -Dcatalina.base=/www/server/tomcat8 -Dcatalina.home=/www/server/tomcat8 -Djava.io.tmpdir=/www/server/tomcat8/temp org.apache.catalina.startup.Bootstrap
root 740852 1 0 Jun15 ? 00:00:00 sudo -u springboot nohup /usr/java/jdk1.8.0_121/bin/java -jar /www/wwwroot/api.fengniaofocus.com/test/bird-0.0.2-SNAPSHOT.jar --server.port=6054 --spring.profiles.active=online
想办法启动 jsvc.exec -java-home /usr/java/jdk1.8.0_121 -user 。。。。
问题描述:上传到服务器的文件访问不到,报403
问题排查:上传的文件权限默认为不允许读写
问题解决:查看服务器的umask值,修改为0022
//使用 umask 0022设置为0022
umask 0022
//然后修改 vim /etc/bashrc 文件 ,最后一行修改为 umask 0022 如下图所示即可
vim /etc/bashrc
umask值用于设置用户在创建文件时的默认权限,当我们在系统中创建目录或文件时,目录或文件所具有的默认权限就是由umask值决定的。
注意事项:
-
设置完之后只针对之后新建的文件夹生效,老文件夹建议手动修改访问权限或者删除
-
设置完建议重启一下服务器
umask备注:
三、 springboot上传文件到linux服务器,通过Nginx访问文件时报403 13: Permission denied)
先说原因,是因为上传到linux服务器的文件默认权限是 -rw-------,就是中有所有者才能读与写,在服务器上传代码中添加
dest.setExecutable(false, false);//不能执行
dest.setWritable(true, true);//所有者可写
dest.setReadable(true, false);//可读
这三句就可以了,此时上传的文件就是 -rw-r–r-- 权限,nigix可以正常访问
全部代码如下: ltkj是通过方法2 Nginx root用户 解决的, 方法3 未验证 待验证
/**
* 上传更新
* @param app
* @param appId
* @return
*/
@PostMapping("/uploadApp")
@ResponseBody
public GneResult<GApp> uploadApp(@NotNull(message = "51016") @RequestParam("app") MultipartFile app,
@NotNull(message = "51016") @RequestParam("appId") String appId) {
String filename = "XXXX";
String filepath = uploadDir + filename;
File dest = new File(filepath);
if(dest.exists()) { //文件存在
int i = filename.lastIndexOf(".");
String name = filename.substring(0, i);
String suffix = filename.substring(i);
FileUtil.copy(dest, new File(uploadDir+name+"-org"+suffix), true);
FileUtil.del(dest);
}else if (!dest.getParentFile().exists()) { //判断文件父目录是否存在
dest.getParentFile().mkdirs();
}
try {
app.transferTo(dest); //保存文件
// 权限
dest.setExecutable(false, false);
dest.setWritable(true, true);
dest.setReadable(true, false);
} catch (IOException e) {
e.printStackTrace();
return GneResult.error(e.getMessage());
}
return GneResult.ok();
}