# stage04-04 **Repository Path**: null_631_9084/stage04-04 ## Basic Information - **Project Name**: stage04-04 - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2020-10-09 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README **作业一:** 业务场景:用户上传的头像图片大小不一、手机和PC等设备显示尺寸也存在差异,因此需要能根据http请求指定的尺寸参数对图片进行动态压缩,以达到屏幕适配的作用。 功能需求:搭建FastDFS图片服务器,通过http请求访问服务器中图片时,显示动态缩略图。具体要求如下: - 在Linux系统中安装FastDFS服务器 - 可以使用FastDFS自带的工具将文件上传到FastDFS - 通过http访问某个图片时,FastDFS通过GraphicsMagick工具生成缩略图,将动态缩略图响应输出 作业要求: - 提供Linux下的安装步骤文档 作业提示: \1. GraphicsMagick选择1.3.18版本,安装完成之后测试是否支持png、jpg,以及验证gm是否可用 \2. 安装LuaJIT-2.0.4、lua-nginx-module-0.8.10和ngx_devel_kit-0.2.18 \3. 安装Nginx选择nginx-1.4.2版本,安装完成后测试lua环境是否支持,比如输出hello world ### Nginx-Lua-FastDFS-GraphicsMagick #### FastDFS安装 单机与Nginx https://blog.csdn.net/ko0491/article/details/108884243 集群与Nginx https://blog.csdn.net/ko0491/article/details/108888445 ### LuaJIT http://luajit.org/download.html ##### 安装lua环境 ```shell tar -zxvf LuaJIT-2.0.5.tar.gz cd LuaJIT-2.0.5 make && make install ``` #### 配置lua环境变量 ```shell export LUAJIT_LIB=/usr/local/lib export LUAJIT_INC=/usr/local/include/luajit-2.0 ``` ### GraphicsMagick ftp://ftp.graphicsmagick.org/pub/GraphicsMagick/1.3/ #### 安装GraphicsMagick ```shell tar -zxvf GraphicsMagick-1.3.26.tar.gz cd GraphicsMagick-1.3.26 mkdir /data/local/GraphicsMagick -p ./configure --prefix=/data/local/GraphicsMagick --enable-shared make && make install ``` * 查看 ```shell /data/local/GraphicsMagick/bin/gm -version ``` ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200930205237809.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2tvMDQ5MQ==,size_16,color_FFFFFF,t_70#pic_center) #### lua-nginx-module https://github.com/openresty/lua-nginx-module/tags #### ngx_devel_kit/ https://github.com/vision5/ngx_devel_kit/tags ```shell ./configure --prefix=/usr/local/nginx --add-module=/usr/local/fastdfs/fastdfs-nginx-module-1.20/src --add-module=/usr/local/graphicsMagick/lua-nginx-module-0.10.14 --add-module=/usr/local/graphicsMagick/ngx_devel_kit-0.3.1 make && make install ``` ### 从github上下载lua脚本nginx-lua-fastdfs-GraphicsMagick ```shell git clone https://github.com/hpxl/nginx-lua-fastdfs-GraphicsMagick.git cd nginx-lua-fastdfs-GraphicsMagick/lua cp ./* /usr/local/nginx/conf/lua ``` ### 修改配置 ```shell vim /usr/local/nginx/conf/lua/fastdfs.lua ``` ```shell #在46行 fdfs:set_tracker("你的ip192.168.181.135", 22122) #在72行 local command = "/data/local/GraphicsMagick/bin/gm convert " .. originalFile .. " -thumbnail " .. area .. " -background gray -gravity center -extent " .. area .. " " .. ngx.var.file; ``` * 完整 ``` -- 写入文件 local function writefile(filename, info) local wfile=io.open(filename, "w") --写入文件(w覆盖) assert(wfile) --打开时验证是否出错 wfile:write(info) --写入传入的内容 wfile:close() --调用结束后记得关闭 end -- 检测路径是否目录 local function is_dir(sPath) if type(sPath) ~= "string" then return false end local response = os.execute( "cd " .. sPath ) if response == 0 then return true end return false end -- 检测文件是否存在 local file_exists = function(name) local f=io.open(name,"r") if f~=nil then io.close(f) return true else return false end end local area = nil local originalUri = ngx.var.uri; local originalFile = ngx.var.file; local index = string.find(ngx.var.uri, "([0-9]+)x([0-9]+)"); if index then originalUri = string.sub(ngx.var.uri, 0, index-2); area = string.sub(ngx.var.uri, index); index = string.find(area, "([.])"); area = string.sub(area, 0, index-1); local index = string.find(originalFile, "([0-9]+)x([0-9]+)"); originalFile = string.sub(originalFile, 0, index-2) end -- check original file if not file_exists(originalFile) then local fileid = string.sub(originalUri, 2); -- main local fastdfs = require('restyfastdfs') local fdfs = fastdfs:new() fdfs:set_tracker("192.168.181.135", 22122) fdfs:set_timeout(1000) fdfs:set_tracker_keepalive(0, 100) fdfs:set_storage_keepalive(0, 100) local data = fdfs:do_download(fileid) if data then -- check image dir if not is_dir(ngx.var.image_dir) then os.execute("mkdir -p " .. ngx.var.image_dir) end writefile(originalFile, data) end end -- 创建缩略图 local image_sizes = {"80x80", "800x600", "40x40", "60x60","200x200","100x100"}; function table.contains(table, element) for _, value in pairs(table) do if value == element then return true end end return false end if table.contains(image_sizes, area) then local command = "/data/local/GraphicsMagick/bin/gm convert " .. originalFile .. " -thumbnail " .. area .. " -background gray -gravity center -extent " .. area .. " " .. ngx.var.file; -- local command = "gm convert " .. originalFile .. " -thumbnail " .. area .. " -background gray -gravity center -extent " .. area .. " " .. ngx.var.file; os.execute(command); end; if file_exists(ngx.var.file) then --ngx.req.set_uri(ngx.var.uri, true); ngx.exec(ngx.var.uri) else ngx.exit(404) end ``` ### 修改nginx.conf ```shell server { listen 8888; # server_name localhost; # location ~/group[0-9]/ { # ngx_fastdfs_module; # } location /group1/M00 { alias /home/fastdfs/data; set $image_root "/home/fastdfs/data"; if ($uri ~ "/([a-zA-Z0-9]+)/([a-zA-Z0-9]+)/([a-zA-Z0-9]+)/([a-zA-Z0-9]+)/(.*)") { set $image_dir "$image_root/$3/$4/"; set $image_name "$5"; set $file "$image_dir$image_name"; } if (!-f $file) { content_by_lua_file "/usr/local/nginx/conf/lua/fastdfs.lua"; } ngx_fastdfs_module; } } ``` #### 修改图片目录赋予网站用户写的权限 chmod -R 777 /home/fastdfs/data/ #### 启动Nginx 若出错,如/usr/local/nginx/sbin/nginx: error while loading shared libraries: libluajit-5.1.so.2: cannot open shared object file: No such file or directory 请按如下操作: find / -name libluajit-5.1.so.2 ln -s /usr/local/lib/libluajit-5.1.so.2 /usr/lib64/libluajit-5.1.so.2 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20201009101848266.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2tvMDQ5MQ==,size_16,color_FFFFFF,t_70#pic_center) ![在这里插入图片描述](https://img-blog.csdnimg.cn/20201009101905486.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2tvMDQ5MQ==,size_16,color_FFFFFF,t_70#pic_center) #### detected a LuaJIT version which is not OpenResty's; ``` [alert] 12687#0: detected a LuaJIT version which is not OpenResty's; many optimizations will be disabled and performance will be compromised (see https://github.com/openresty/luajit2 for OpenResty's LuaJIT or, even better, consider using the OpenResty releases from https://openresty.org/en/download.html) ``` 这个倒问题不大,是个warn而已,需要卸载之前的luajit,到他说的网站去下载。 先卸载原有luagit ```shell cd /usr/locat/lua/LuaJIT-2.0.4 make uninstall ``` 然后从https://github.com/openresty/luajit2下载安装 ```shell git clone https://github.com/openresty/luajit2 cd luajit2 make && make install ``` 剩下的步骤跟一开始装luajit是一样的。具体的看自己的目录写。 ```shell export LUAJIT_LIB=/usr/local/lib export LUAJIT_INC=/usr/local/include/luajit-2.1 ``` 然后重新编译nginx ### 问题 -v0.10.16安装里用了16版,会有这个问题,降到14就好了 ##### nginx使用openresty时failed to load the resty.core module ``` nginx: [alert] failed to load the 'resty.core' module (https://github.com/openresty/lua-resty-core); ensure you are using an OpenResty release from openresty.org/en/download.html (reason: module 'resty.core' not found: no field package.preload['resty.core'] no file './resty/core.lua' no file '/usr/local/share/luajit-2.1.0-beta3/resty/core.lua' no file '/usr/local/share/lua/5.1/resty/core.lua' no file '/usr/local/share/lua/5.1/resty/core/init.lua' no file './resty/core.so' no file '/usr/local/lib/lua/5.1/resty/core.so' no file '/usr/local/lib/lua/5.1/loadall.so' no file './resty.so' no file '/usr/local/lib/lua/5.1/resty.so' no file '/usr/local/lib/lua/5.1/loadall.so') in /usr/local/nginx/conf/nginx.conf:222 ``` 下载 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20201009120543983.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2tvMDQ5MQ==,size_16,color_FFFFFF,t_70#pic_center) ``` wget https://github.com/openresty/lua-nginx-module/archive/v0.10.14.tar.gz ``` 下载完成后重新编译nginx ### **作业二:** 使用SpringBoot和OSS实现图片的上传、下载和删除功能, 具体要求如下 - 可以使用postman 发送上传请求 /oss/upload ,实现图片上传到OSS对应的Bucket中 类型检查:必须为 jpg、png 或者 jpeg类型,其它图片类型返回错误提示信息 大小检查:必须小于5M,大于5M时返回错误提示信息 图片名称:生成的文件名,必须保持唯一 - 可以使用postman 发送下载请求 /oss/download,实现图片下载 ~~~java 作业二: 使用SpringBoot和OSS实现图片的上传、下载和删除功能, 具体要求如下 可以使用postman 发送上传请求 /oss/upload ,实现图片上传到OSS对应的Bucket中 类型检查:必须为 jpg、png 或者 jpeg类型,其它图片类型返回错误提示信息 ```xml com.aliyun.oss aliyun-sdk-oss 3.11.1 ``` ### controller ```java package com.liu.oos.controller; import com.aliyun.oss.OSS; import com.aliyun.oss.model.OSSObject; import com.aliyun.oss.model.PutObjectResult; import com.liu.oos.config.AliyunConfig; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.apache.tomcat.util.http.fileupload.IOUtils; import org.joda.time.DateTime; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.nio.file.Path; import java.nio.file.Paths; import java.util.UUID; @RestController public class AliyunUploaderController { @Autowired private OSS ossClient; @Autowired private AliyunConfig aliyunConfig; /** * windows文件路径分隔符\ */ public static final char WIN_SEPARATOR = '\\'; /** * unix文件路径分隔符/ */ public static final char UNIX_SEPARATOR = '/'; public final static String[] IMAGE_EXTS ={".jpg",".png",".jpeg"}; @RequestMapping("/oss/upload") public String upload(MultipartFile uploadFile) throws IOException { String originalFileName = uploadFile.getOriginalFilename(); // 部分浏览器可能带路径,删除路径部分 if (originalFileName.indexOf(UNIX_SEPARATOR) >= 0) { originalFileName = getFilename(originalFileName); } String extension = getExtension(originalFileName, true); if(!ArrayUtils.contains(IMAGE_EXTS,extension)){ return "不支持的类型" ; } System.out.println(uploadFile.getInputStream().available()); if(uploadFile.getInputStream().available()>1024 * 1024 * 5){ return "文件大于5M"; } String newName= getFilePath(originalFileName); newName="test/"+newName; PutObjectResult putObjectResult = ossClient.putObject(aliyunConfig.getBucketName(), newName, new ByteArrayInputStream(uploadFile.getBytes())); return newName; } @RequestMapping("/oss/download") public byte[] download(String objName) throws IOException { OSSObject object = ossClient.getObject(aliyunConfig.getBucketName(), objName); InputStream objectContent = object.getObjectContent(); if (objectContent != null) { ByteArrayOutputStream output = new ByteArrayOutputStream(); IOUtils.copy(objectContent, output); objectContent.close(); return output.toByteArray(); } return null; } @RequestMapping("/oss/delete") public void delete(String objName){ ossClient.deleteObject(aliyunConfig.getBucketName(),objName); } public static String getFilename(final String filePath) { Path p = Paths.get(filePath); return p.getFileName() .toString(); } public static String getExtension(final String filename, final boolean includePoint) { if (StringUtils.isNotEmpty(filename)) { int i = filename.lastIndexOf('.'); if ((i > 0) && (i < (filename.length() - 1))) { return includePoint ? (filename.substring(i)).toLowerCase() : (filename.substring(i + 1)).toLowerCase(); } } return StringUtils.EMPTY; } // 生成不重复的文件路径和文件名 private String getFilePath(String sourceFileName) { DateTime dateTime = new DateTime(); return "images/" + dateTime.toString("yyyy") + "/" + dateTime.toString("MM") + "/" + dateTime.toString("dd") + "/" + UUID.randomUUID().toString() + "." + StringUtils.substringAfterLast(sourceFileName, "."); } } ``` ~~~