我带的实习生竟然把照片直接存到了服务器上!崩溃了
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">小二是新来的实习生,<span style="color: black;">做为</span>技术 leader,我给他安排了一个非常简单的练手任务,把前端 markdown 编辑器里上传的<span style="color: black;">照片</span><span style="color: black;">保留</span>到服务器端,结果他真的就把<span style="color: black;">照片</span>直接<span style="color: black;">保留</span>到了服务器上,这下可把我气坏了,就<span style="color: black;">不可</span>搞个对象存储服务,<span style="color: black;">例如</span>说 OSS、MinIO?</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">他理直气壮地反驳道:“谁让你不讲清楚,我去找老板把你开掉!”我瞬间就怂了,说,“来来来,我手把手教你怎么把<span style="color: black;">照片</span><span style="color: black;">保留</span>到 OSS 上,好<span style="color: black;">欠好</span>?”</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">“<span style="color: black;">不消</span>了,还是我来教你吧。”小二非常自信,下面是他在 Spring Boot 应用中整合 OSS 做的记录。</span></p>
<h1 style="color: black; text-align: left; margin-bottom: 10px;"><span style="color: black;">1、</span>开通 OSS</h1>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">OSS <span style="color: black;">亦</span><span style="color: black;">便是</span> Object Storage Service,是阿里云<span style="color: black;">供给</span>的一套对象存储服务,国内的竞品还有七牛云的 Kodo和腾讯云的COS。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">第1</span>步,登录阿里云官网,搜索“OSS”关键字,进入 OSS <span style="color: black;">制品</span>页。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">第二步,<span style="color: black;">倘若</span>是 OSS 新用户的话,<span style="color: black;">能够</span>享受 6 个月的新人专享优惠价,<span style="color: black;">不外</span>续费的时候还是会肉疼。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">第三步,进入 OSS 管理<span style="color: black;">掌控</span>台,点击「Bucket 列表」,点击「创建 Bucket」。</span></p>
<div style="color: black; text-align: left; margin-bottom: 10px;"><img src="https://p3-sign.toutiaoimg.com/tos-cn-i-qvj2lq49k0/24d7c9e444a14f99b3063fdaed7f2b33~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1729712146&x-signature=t7Carj6OsBnZOYY2EErJaUC6TV0%3D" style="width: 50%; margin-bottom: 20px;"></div>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">Bucket 的词面意思是桶,<span style="color: black;">这儿</span>指存储空间,<span style="color: black;">便是</span>用于存储对象的容器。<span style="color: black;">重视</span>读写权限为“公共读”,<span style="color: black;">亦</span><span style="color: black;">便是</span><span style="color: black;">准许</span>互联网用户<span style="color: black;">拜访</span>云空间上的<span style="color: black;">照片</span>。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">第四步,点击「确定」就算是开通成功了。</span></p>
<h1 style="color: black; text-align: left; margin-bottom: 10px;"><span style="color: black;">2、</span>整合 OSS</h1>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">第1</span>步,在 pom.xml 文件中添加 OSS 的依赖。</span></p><span style="color: black;"><!-- 阿里云 OSS --></span>
<span style="color: black;"><<span style="color: black;">dependency</span>></span>
<span style="color: black;"><<span style="color: black;">groupId</span>></span>com.aliyun.oss<span style="color: black;"></<span style="color: black;">groupId</span>></span>
<span style="color: black;"><<span style="color: black;">artifactId</span>></span>aliyun-sdk-oss<span style="color: black;"></<span style="color: black;">artifactId</span>></span>
<span style="color: black;"><<span style="color: black;">version</span>></span>3.10.2<span style="color: black;"></<span style="color: black;">version</span>></span>
<span style="color: black;"></<span style="color: black;">dependency</span>></span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">第二步,在 application.yml 文件中添加 OSS 配置项。</span></p><span style="color: black;">aliyun:</span>
<span style="color: black;">oss:</span>
<span style="color: black;"># oss对外服务的<span style="color: black;">拜访</span>域名</span>
<span style="color: black;">endpoint:</span> <span style="color: black;">oss-cn-beijing.aliyuncs.com</span>
<span style="color: black;"># <span style="color: black;">拜访</span>身份验证中用到用户标识</span>
<span style="color: black;">accessKeyId:</span> <span style="color: black;">LTAI5</span>
<span style="color: black;"># 用户用于加密签名字符串和oss用来验证签名字符串的密钥</span>
<span style="color: black;">accessKeySecret:</span> <span style="color: black;">RYN</span>
<span style="color: black;"># oss的存储空间</span>
<span style="color: black;">bucketName:</span> <span style="color: black;">itwanger-oss1</span>
<span style="color: black;"># 上传文件<span style="color: black;">体积</span>(M)</span>
<span style="color: black;">maxSize:</span> <span style="color: black;">3</span>
<span style="color: black;"># 上传文件夹路径前缀</span>
<span style="color: black;">dir:</span>
<span style="color: black;">prefix:</span> <span style="color: black;">codingmore/images/</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">第三步,新增 OssClientConfig.java 配置类,<span style="color: black;">重点</span><span style="color: black;">便是</span><span style="color: black;">经过</span> @Value 注解从配置文件中获取配置项,然后创建 OSSClient。</span></p><span style="color: black;">@Configuration</span>
<span style="color: black;">public</span> <span style="color: black;"><span style="color: black;">class</span> <span style="color: black;">OssClientConfig</span> </span>{
<span style="color: black;">@Value(<span style="color: black;">"<span style="color: black;">${aliyun.oss.endpoint}</span>"</span>)</span>
String endpoint ;
<span style="color: black;">@Value(<span style="color: black;">"<span style="color: black;">${aliyun.oss.accessKeyId}</span>"</span>)</span>String accessKeyId ;<span style="color: black;">@Value(<span style="color: black;">"<span style="color: black;">${aliyun.oss.accessKeySecret}</span>"</span>)</span>
String accessKeySecret;
<span style="color: black;">@Bean</span>
<span style="color: black;">public</span> OSSClient createOssClient() {
<span style="color: black;">return</span>(OSSClient)new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
}
}<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">第四步,新增文件上传接口 OssController.java,参数为 MultipartFile。</span></p><span style="color: black;">@Controller</span>
<span style="color: black;">@Api</span>(tags = <span style="color: black;">"上传"</span>)
<span style="color: black;">@RequestMapping</span>(<span style="color: black;">"/ossController"</span>)
public class OssController {
<span style="color: black;">@Autowired</span>
private IOssService ossService;
<span style="color: black;">@RequestMapping</span>(value = <span style="color: black;">"/upload"</span>,method=RequestMethod.POST)<span style="color: black;">@ResponseBody</span>
<span style="color: black;">@ApiOperation</span>(<span style="color: black;">"上传"</span>)
public ResultObject<String> upload(<span style="color: black;">@RequestParam</span>(<span style="color: black;">"file"</span>) MultipartFile file, HttpServletRequest req) {
<span style="color: black;">return</span> <span style="color: black;">ResultObject</span><span style="color: black;">.success</span>(ossService.upload(file));
}
}
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">第五步,新增 Service,将文件上传到 OSS,并返回文件<span style="color: black;">保留</span>路径。</span></p><span style="color: black;">@Service</span>
<span style="color: black;">public</span> <span style="color: black;"><span style="color: black;">class</span> <span style="color: black;">OssServiceImpl</span> <span style="color: black;">implements</span> <span style="color: black;">IOssService</span></span>{
<span style="color: black;">@Value(<span style="color: black;">"<span style="color: black;">${aliyun.oss.maxSize}</span>"</span>)</span>
<span style="color: black;">private</span> int maxSize;
<span style="color: black;">@Value(<span style="color: black;">"<span style="color: black;">${aliyun.oss.bucketName}</span>"</span>)</span>
<span style="color: black;">private</span> String bucketName;
<span style="color: black;">@Value(<span style="color: black;">"<span style="color: black;">${aliyun.oss.dir.prefix}</span>"</span>)</span>
<span style="color: black;">private</span>String dirPrefix;<span style="color: black;">@Autowired</span>
<span style="color: black;">private</span> OSSClient ossClient;
<span style="color: black;">@Override</span>
<span style="color: black;">public</span> String upload(MultipartFile file) {
<span style="color: black;">try</span> {
<span style="color: black;">return</span>upload(file.getInputStream(), file.getOriginalFilename());
}<span style="color: black;">catch</span> (IOException e) {
LOGGER.error(e.getMessage());
}
<span style="color: black;">return</span> <span style="color: black;">null</span>;
}
<span style="color: black;">@Override</span>
<span style="color: black;">public</span>String upload(InputStream inputStream,String name) {
String objectName = getBucketName(name);<span style="color: black;">// 创建PutObject请求。</span>
ossClient.putObject(bucketName, objectName, inputStream);
<span style="color: black;">return</span>formatPath(objectName);
}<span style="color: black;">private</span> String getBucketName(String url){
String ext = <span style="color: black;">""</span>;
<span style="color: black;">for</span>(String extItem:imageExtension){
<span style="color: black;">if</span>(url.indexOf(extItem) != -<span style="color: black;">1</span>){
ext = extItem;<span style="color: black;">break</span>;
}
}
<span style="color: black;">return</span> dirPrefix+ DateUtil.today()+<span style="color: black;">"/"</span>+ IdUtil.randomUUID()+ext;
}
<span style="color: black;">private</span>String formatPath(String objectName){<span style="color: black;">return</span> <span style="color: black;">"https://"</span> +bucketName+<span style="color: black;">"."</span>+ ossClient.getEndpoint().getHost() + <span style="color: black;">"/"</span> + objectName;
}
}
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">第六步,打开 Apipost,测试 OSS 上传接口,<span style="color: black;">重视</span>参数<span style="color: black;">选取</span>文件,点击发送后<span style="color: black;">能够</span>看到服务器端返回的<span style="color: black;">照片</span>链接。</span></p>
<div style="color: black; text-align: left; margin-bottom: 10px;"><img src="https://p26-sign.toutiaoimg.com/tos-cn-i-qvj2lq49k0/fbe84bbf0c54439f9e6d54b94153f678~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1729712146&x-signature=PuyH19PwdSGGqwPiRsPOAJ%2FzmSA%3D" style="width: 50%; margin-bottom: 20px;"></div>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">第七步,进入阿里云 OSS 后台管理,<span style="color: black;">能够</span>确认<span style="color: black;">照片</span>确实<span style="color: black;">已然</span>上传成功。</span></p>
<div style="color: black; text-align: left; margin-bottom: 10px;"><img src="https://p3-sign.toutiaoimg.com/tos-cn-i-qvj2lq49k0/1ec6d1a798b0403fb71d03754af3ab96~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1729712146&x-signature=I%2Bhu7QenicrEi94OcxU4q%2FDB1Vs%3D" style="width: 50%; margin-bottom: 20px;"></div>
<h1 style="color: black; text-align: left; margin-bottom: 10px;"><span style="color: black;">3、</span>拉取前端代码来测试 OSS 上传接口</h1>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">codingmore-admin-web 是编程喵(Codingmore)的前端管理项目,<span style="color: black;">能够</span><span style="color: black;">经过</span>下面的<span style="color: black;">位置</span>拉取到本地。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">https://github.com/itwanger/codingmore-admin-web</span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">执行 </span><span style="color: black;">yarn run dev</span> 命令后就<span style="color: black;">能够</span><span style="color: black;">起步</span> Web 管理端了,进入到<span style="color: black;">文案</span>编辑页面,<span style="color: black;">选取</span>一张<span style="color: black;">照片</span>进行上传,<span style="color: black;">能够</span>确认<span style="color: black;">照片</span>是<span style="color: black;">能够</span>正常从前端上传到服务器端,服务器端再上传到 OSS,之后再返回前端<span style="color: black;">照片</span><span style="color: black;">拜访</span>链接的。</p>
<div style="color: black; text-align: left; margin-bottom: 10px;"><img src="https://p3-sign.toutiaoimg.com/tos-cn-i-qvj2lq49k0/b17c9d0190f2480bbe2f771971dfd1a2~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1729712146&x-signature=eknKRTo9zDDowDGcG7Kzxqlxdv4%3D" style="width: 50%; margin-bottom: 20px;"></div>
<h1 style="color: black; text-align: left; margin-bottom: 10px;"><span style="color: black;">4、</span>利用 OSS 进行自动转链</h1>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">第1</span>步,在 PostsServiceImpl.java 中添加<span style="color: black;">照片</span>转链的<span style="color: black;">办法</span>,<span style="color: black;">重点</span>利用正则表达式找出<span style="color: black;">文案</span>内容中的外链,<span style="color: black;">而后</span>将外链的<span style="color: black;">照片</span>上传到 OSS,<span style="color: black;">而后</span>再替换掉原来的外链<span style="color: black;">照片</span>。</span></p><span style="color: black;">// 匹配<span style="color: black;">照片</span>的 markdown 语法</span>
<span style="color: black;">// ![](hhhx.png)</span>
<span style="color: black;">// !(hhhx.png?ax)</span>
<span style="color: black;">public</span> <span style="color: black;">static</span> <span style="color: black;">final</span>String IMG_PATTERN =<span style="color: black;">"\\!\\[.*\\]\\((.*)\\)"</span>;
<span style="color: black;"><span style="color: black;">private</span> <span style="color: black;">void</span> <span style="color: black;">handleContentImg</span><span style="color: black;">(Posts posts)</span> </span>{
String content = posts.getPostContent();
Pattern p = Pattern.compile(IMG_PATTERN, Pattern.CASE_INSENSITIVE);
Matcher m = p.matcher(content);
Map<String, Future<String>><span style="color: black;">map</span> = <span style="color: black;">new</span> HashMap<>();
<span style="color: black;">while</span>(m.find()) {
String imageTag = m.group();
LOGGER.info(<span style="color: black;">"<span style="color: black;">运用</span>分组进行替换{}"</span>, imageTag);
String imageUrl = imageTag.substring(imageTag.indexOf(<span style="color: black;">"("</span>) + <span style="color: black;">1</span>, imageTag.indexOf(<span style="color: black;">")"</span>));
<span style="color: black;">// 确认是本站链接,不处理</span>
<span style="color: black;">if</span> (imageUrl.indexOf(iOssService.getEndPoint()) != <span style="color: black;">-1</span>) {
<span style="color: black;">continue</span>;
}
<span style="color: black;">// <span style="color: black;">经过</span>线程池将<span style="color: black;">照片</span>上传到 OSS</span>
Future<String> <span style="color: black;">future</span>= ossUploadImageExecutor.submit(() -> {<span style="color: black;">return</span> iOssService.upload(imageUrl);
});
<span style="color: black;">map</span>.put(imageUrl, <span style="color: black;">future</span>);
}
<span style="color: black;">for</span> (String oldUrl : <span style="color: black;">map</span>.keySet()) {
Future<String><span style="color: black;">future</span> = <span style="color: black;">map</span>.get(oldUrl);
<span style="color: black;">try</span> {
String imageUrl = <span style="color: black;">future</span>.get();
content = content.replace(oldUrl, imageUrl);
} <span style="color: black;">catch</span>(InterruptedException | ExecutionException e) {
LOGGER.error(<span style="color: black;">"获取<span style="color: black;">照片</span>链接出错{}"</span>, e.getMessage());
}
}
posts.setPostContent(content);
}
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">第二步,在 OssServiceImpl.java 中添加<span style="color: black;">按照</span>外链<span style="color: black;">位置</span>上传<span style="color: black;">照片</span>到 OSS 的<span style="color: black;">办法</span>。</span></p><span style="color: black;">public</span> <span style="color: black;">String</span> upload(<span style="color: black;">String</span> url) {
<span style="color: black;">String</span> objectName = getFileName(url);
<span style="color: black;">try</span> (InputStream inputStream = <span style="color: black;">new</span>URL(url).openStream()) {
ossClient.putObject(bucketName, objectName, inputStream);
}<span style="color: black;">catch</span> (IOException e) {
LOGGER.error(e.getMessage());
}
<span style="color: black;">return</span>formatOSSPath(objectName);
}<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">第三步,<span style="color: black;">经过</span> Web 管理端来测试外链<span style="color: black;">是不是</span>转链成功。先找两张外链的<span style="color: black;">照片</span>,<span style="color: black;">能够</span>看到 markdown 在预览的时候就不<span style="color: black;">表示</span>。</span></p>
<div style="color: black; text-align: left; margin-bottom: 10px;"><img src="https://p3-sign.toutiaoimg.com/tos-cn-i-qvj2lq49k0/733b615200884ff3a137317b9017138c~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1729712146&x-signature=qnccKyzMVrbsAGCJN6WpP3qZ6wI%3D" style="width: 50%; margin-bottom: 20px;"></div>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">而后</span><span style="color: black;">咱们</span>点击发布,<span style="color: black;">能够</span>看到两张<span style="color: black;">照片</span>都正常<span style="color: black;">表示</span>了,<span style="color: black;">由于</span>转<span style="color: black;">成为了</span> OSS 的<span style="color: black;">照片</span><span style="color: black;">拜访</span><span style="color: black;">位置</span>。</span></p>
<div style="color: black; text-align: left; margin-bottom: 10px;"><img src="https://p3-sign.toutiaoimg.com/tos-cn-i-qvj2lq49k0/1bee9cd009ec4e85a7d574cb4bb98cb9~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1729712146&x-signature=ZL3biA5fwHZflwr%2BNbvhgH49Yjc%3D" style="width: 50%; margin-bottom: 20px;"></div>
<h1 style="color: black; text-align: left; margin-bottom: 10px;"><span style="color: black;">5、</span>小结</h1>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">综上来看,实习生小二在 Spring Boot 中整合 OSS 的代码还是挺<span style="color: black;">可靠</span>的。<span style="color: black;">亦</span>许 OSS+CDN 才是图床的最好<span style="color: black;">处理</span><span style="color: black;">方法</span>,<span style="color: black;">不外</span>阿里云的 HTTPS CDN 在 GitHub 上<span style="color: black;">没法</span>回源<span style="color: black;">引起</span><span style="color: black;">照片</span>不<span style="color: black;">表示</span>的问题仍然<span style="color: black;">无</span>得到有效的<span style="color: black;">处理</span>。</span></p>
楼主继续加油啊!外链论坛加油! 期待更新、坐等、迫不及待等。
页:
[1]