在绝大多数的项目中都会涉及到文件上传等,下面我们来说一下技术派中是如何实现原生图片上传的,这个功能说起来简单,但其实对于技术还是有考验的。图片的上传涉及到IO读写,一个文件上传的功能,就可以把IO流涉及到的知识点全覆盖,比如字节流ByteArrayInputStream、缓存流BufferedOutputStream、文件File的读写权限、文件魔数等等。
如果你想实现一个自己的文件读写Util类,需要考虑的细节还是很多的,比如静态资源的配置、图片大小限制、前端图片上传组件,后端图片接收参数MutiparHttpServletRequest等等。
技术派中关于图片上传的入口有三处:
看发表文章时,涉及到四种方式:
这四种方式都会出发图片上传功能(严格一点,后面两个还涉及到图片转链)后台的接口都是一样的,都调用的是ImageRestController,上传图片调用的是upload方法,请求参数为HttpServletRequest;转存图片链接调用的是save方法,参数为图片的外部链接。响应的结果为ResVo
image: abs-tmp-path: /tmp/storage/ web-img-path: /forum/image/ tmp-upload-path: /tmp/forum/ cdn-host: oss: type: local prefix: paicoding/ endpoint: ak: sk: bucket: host: https://cdn.tobebetterjavaer.com spring: web: resources: # 支持本地图片上传之后的链接,其中 file:///d的用于win系统,后面的file: 适用于mac/linux系统 static-locations: - classpath:/static/ - file:///d:${image.abs-tmp-path} - file:${image.abs-tmp-path} 来解释一下参数的含义:
静态资源通常包括CSS、JavaScript、图片等文件,通过设置spring: web: resources: static-locations,我们可以告诉 Spring Boot 在哪些位置查找静态资源。 Spring Boot 的默认静态资源位置包括;

当我们为spring.web.resources.static-locations 提供自定义的值时,Spring Boot会覆盖这些默认值。在技术派的项目结构中,我们将CSS和javaScript,以及一些图片资源放在了,paicoding-ui模块static目录下。

也就意味着,在我们的前端页面中,如果遇到类似这样的请求时,Spring Boot将会从 classpath:/static/目录下去找。

注意,我们还指定了另外两个静态资源位置:file:///d:${image.abs-tmp-path} 和file:${image.abs-tmp-path} ,前者用于Windows系统 ,后者用于macOS和Linux系统。用macOs举例,我们会把图片保存在 /tmp/storage/forum/image目录下。

也就是说,我们可以通过 http://127.0.0.1:8080/forum/image/20230423060009676_69.jpg这种形式访问图片。
file:/是一个URI(统一资源标识符)的方案,表示在本地文件上的系统资源。例如,如果你想要引用本地文件系统上的一个文件,可以使用file:/。以下是一些实例:
使用@ConfigurationProperties 注解使其和配置文件中的图片配置关联起来。
@Setter @Getter @Component @ConfigurationProperties(prefix = "image") public class ImageProperties { /** * 存储绝对路径 */ private String absTmpPath; /** * 存储相对路径 */ private String webImgPath; /** * 上传文件的临时存储目录 */ private String tmpUploadPath; /** * 访问图片的host */ private String cdnHost; private OssProperties oss; public String buildImgUrl(String url) { if (!url.startsWith(cdnHost)) { return cdnHost + url; } return url; } } 我们先来看比较简单的一种,上传文章封面,在发表文章的页面,点击保存按钮,会弹出文章封面的上传模态框。

代码非常简单,用了一个input组件,type为file,接受的文件类型为image。
当选择图片后,会触发change事件。