SpringBoot整合阿里云OSS文件上传、下载、查看、删除

news2025/7/28 4:09:23

SpringBoot整合阿里云OSS文件上传、下载、查看、删除

  • 1、开发准备
    • 1.1 前置知识
    • 1.2 环境参数
    • 1.3 你能学到什么
  • 2. 使用阿里云OSS
    • 2.1 创建Bucket
    • 2.2 管理文件
    • 2.3 阿里云OSS文档
  • 3. 项目初始化
    • 3.1 创建SpringBoot项目
    • 3.2 Maven依赖
    • 3.3 安装lombok插件
  • 4. 后端服务编写
    • 4.1 阿里云OSS配置
    • 4.2 后端业务
      • 4.2.1 vo
      • 4.2.2 service
      • 4.2.3 controller
  • 5. 前端页面编写与测试
    • 5.1 文件上传页面
    • 5.2 文件管理页面

1、开发准备

1.1 前置知识

java基础以及SpringBoot简单基础知识即可。

1.2 环境参数

  • 开发工具:IDEA
  • 基础环境:Maven+JDK8
  • 所用技术:SpringBoot、lombok、阿里云OSS存储服务
  • SpringBoot版本:2.1.4

1.3 你能学到什么

  • OSS简介,以及阿里云OSS控制台快速入门使用
  • SpringBoot 整合 阿里云OSS 存储服务,进行文件上传、下载、查看、删除
  • 阿里云OSS文档介绍,以及快速入门使用
  • lombak入门使用以及IDEA lombak插件安装
  • SpringMVC与AJAX前后端分离交互
  • AJAX文件异步上传

2. 使用阿里云OSS

对象存储OSS的多重冗余架构设计,为数据持久存储提供可靠保障。

2.1 创建Bucket

使用OSS,首先需要创建Bucket,Bucket翻译成中文是水桶的意思,把存储的图片资源看做是水,想要盛水必须得
有桶。
进入控制台,https://oss.console.aliyun.com/overview
在这里插入图片描述
在这里插入图片描述
创建完成后,在左侧可以看到已经创建好的Bucket:
在这里插入图片描述
选择Bucket后,即可看到对应的信息,如:url、消耗流量等
在这里插入图片描述

2.2 管理文件

可以通过在线的方式进行管理文件
在这里插入图片描述

2.3 阿里云OSS文档

阿里云OSS文档
在这里插入图片描述
右侧的开发指南说的更加详细
在这里插入图片描述
阿里云虽然提供了完整的文档,但是做一个完整的前后端交互的文件上传、下载、查看、删除等操作,对于小白来说还是有点难度的,所以我把自己学习OSS的步骤以及代码分享了出来,共有需要的人使用。

3. 项目初始化

3.1 创建SpringBoot项目

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.2 Maven依赖

<dependency>
            <groupId>com.aliyun.oss</groupId>
            <artifactId>aliyun-sdk-oss</artifactId>
            <version>2.8.3</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.4</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>joda-time</groupId>
            <artifactId>joda-time</artifactId>
            <version>2.9.9</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.8.1</version>
        </dependency>

3.3 安装lombok插件

因为项目中使用了lombok的@Data注解,当然你也可以自己写get、set等方法。
File——>settings——>Plugins
在这里插入图片描述
在这里插入图片描述
然后restart IDEA即可。

4. 后端服务编写

在这里插入图片描述

4.1 阿里云OSS配置

在resource下新建一个application-oss.properties

aliyun.endpoint=oss-cn-shanghai.aliyuncs.com
aliyun.accessKeyId=你的accessKeyId
aliyun.accessKeySecret=你的accessKeySecret
aliyun.bucketName=gaojun-testbucket
aliyun.urlPrefix=http://gaojun-testbucket.oss-cn-shanghai.aliyuncs.com/

在这里插入图片描述
在这里插入图片描述
在java的包下新建一个config包,创建一个AliyunConfig.java

package com.example.ossdemo.config;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClient;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
/**
 * @desc
 *
 * @author gaojun
 * @email 15037584397@163.com
 */
@Configuration
@PropertySource(value = {"classpath:application-oss.properties"})
@ConfigurationProperties(prefix = "aliyun")
@Data
public class AliyunConfig {
    private String endpoint;
    private String accessKeyId;
    private String accessKeySecret;
    private String bucketName;
    private String urlPrefix;
    @Bean
    public OSS oSSClient() {
        return new OSSClient(endpoint, accessKeyId, accessKeySecret);
    }
}

4.2 后端业务

4.2.1 vo

package com.example.ossdemo.vo;
import lombok.Data;
/**
 * @author gaojun
 * @desc 用于前后端交互的返回值
 * @email 15037584397@163.com
 */
@Data
public class FileUploadResult {
    // 文件唯一标识
    private String uid;
    // 文件名
    private String name;
    // 状态有:uploading done error removed
    private String status;
    // 服务端响应内容,如:'{"status": "success"}'
    private String response;
}

4.2.2 service

package com.example.ossdemo.service;
import com.aliyun.oss.OSS;
import com.aliyun.oss.model.*;
import com.example.ossdemo.config.AliyunConfig;
import com.example.ossdemo.vo.FileUploadResult;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.util.List;
/**
 * @author gaojun
 * @desc
 * @email 15037584397@163.com
 */
@Service
public class FileUploadService {
    // 允许上传的格式
    private static final String[] IMAGE_TYPE = new String[]{".bmp", ".jpg",
            ".jpeg", ".gif", ".png"};
    @Autowired
    private OSS ossClient;
    @Autowired
    private AliyunConfig aliyunConfig;
    /**
     * @author gaojun
     * @desc 文件上传
     *  文档链接 https://help.aliyun.com/document_detail/84781.html?spm=a2c4g.11186623.6.749.11987a7dRYVSzn
     * @email 15037584397@163.com
     */
    public FileUploadResult upload(MultipartFile uploadFile) {
        // 校验图片格式
        boolean isLegal = false;
        for (String type : IMAGE_TYPE) {
            if (StringUtils.endsWithIgnoreCase(uploadFile.getOriginalFilename(),
                    type)) {
                isLegal = true;
                break;
            }
        }
        //封装Result对象,并且将文件的byte数组放置到result对象中
        FileUploadResult fileUploadResult = new FileUploadResult();
        if (!isLegal) {
            fileUploadResult.setStatus("error");
            return fileUploadResult;
        }
        //文件新路径
        String fileName = uploadFile.getOriginalFilename();
        String filePath = getFilePath(fileName);
        // 上传到阿里云
        try {
            ossClient.putObject(aliyunConfig.getBucketName(), filePath, new
                    ByteArrayInputStream(uploadFile.getBytes()));
        } catch (Exception e) {
            e.printStackTrace();
            //上传失败
            fileUploadResult.setStatus("error");
            return fileUploadResult;
        }
        fileUploadResult.setStatus("done");
        fileUploadResult.setResponse("success");
        //this.aliyunConfig.getUrlPrefix() + filePath 文件路径需要保持数据库
        fileUploadResult.setName(this.aliyunConfig.getUrlPrefix() + filePath);
        fileUploadResult.setUid(String.valueOf(System.currentTimeMillis()));
        return fileUploadResult;
    }
    /**
     * @author gaojun
     * @desc 生成路径以及文件名 例如://images/2019/04/28/15564277465972939.jpg
     * @email 15037584397@163.com
     */
    private String getFilePath(String sourceFileName) {
        DateTime dateTime = new DateTime();
        return "images/" + dateTime.toString("yyyy")
                + "/" + dateTime.toString("MM") + "/"
                + dateTime.toString("dd") + "/" + System.currentTimeMillis() +
                RandomUtils.nextInt(100, 9999) + "." +
                StringUtils.substringAfterLast(sourceFileName, ".");
    }
    /**
     * @author gaojun
     * @desc 查看文件列表
     * 文档链接 https://help.aliyun.com/document_detail/84841.html?spm=a2c4g.11186623.2.13.3ad5b5ddqxWWRu#concept-84841-zh
     * @email 15037584397@163.com
     */
    public List<OSSObjectSummary> list() {
        // 设置最大个数。
        final int maxKeys = 200;
        // 列举文件。
        ObjectListing objectListing = ossClient.listObjects(new ListObjectsRequest(aliyunConfig.getBucketName()).withMaxKeys(maxKeys));
        List<OSSObjectSummary> sums = objectListing.getObjectSummaries();
        return sums;
    }
    /**
     * @author gaojun
     * @desc 删除文件
     * 文档链接 https://help.aliyun.com/document_detail/84842.html?spm=a2c4g.11186623.6.770.4f9474b4UYlCtr
     * @email 15037584397@163.com
     */
    public FileUploadResult delete(String objectName) {
        ossClient.deleteObject(aliyunConfig.getBucketName(), objectName);
        FileUploadResult fileUploadResult = new FileUploadResult();
        fileUploadResult.setName(objectName);
        fileUploadResult.setStatus("removed");
        fileUploadResult.setResponse("success");
        return fileUploadResult;
    }
    /**
     * @author gaojun
     * @desc 下载文件
     * 文档链接 https://help.aliyun.com/document_detail/84823.html?spm=a2c4g.11186623.2.7.37836e84ZIuZaC#concept-84823-zh
     * @email 15037584397@163.com
     */
    public InputStream exportOssFile(String objectName) {
        // ossObject包含文件所在的存储空间名称、文件名称、文件元信息以及一个输入流。
        OSSObject ossObject = ossClient.getObject(aliyunConfig.getBucketName(), objectName);
        // 读取文件内容。
        InputStream is = ossObject.getObjectContent();
        return is;
    }
}

4.2.3 controller

package com.example.ossdemo.controller;
import com.aliyun.oss.model.OSSObjectSummary;
import com.example.ossdemo.service.FileUploadService;
import com.example.ossdemo.vo.FileUploadResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
/**
 * @author gaojun
 * @desc
 * @email 15037584397@163.com
 */
@Controller
public class FileUploadController {
    @Autowired
    private FileUploadService fileUploadService;
    /**
     * @author gaojun
     * @desc 文件上传到oss
     * @return FileUploadResult
     * @Param uploadFile
     */
    @RequestMapping("file/upload")
    @ResponseBody
    public FileUploadResult upload(@RequestParam("file") MultipartFile uploadFile)
            throws Exception {
        return this.fileUploadService.upload(uploadFile);
    }
    /**
     * @return FileUploadResult
     * @desc 根据文件名删除oss上的文件
     * http://localhost:8080/file/delete?fileName=images/2019/04/28/1556429167175766.jpg
     * @author gaojun
     * @Param objectName
     */
    @RequestMapping("file/delete")
    @ResponseBody
    public FileUploadResult delete(@RequestParam("fileName") String objectName)
            throws Exception {
        return this.fileUploadService.delete(objectName);
    }
    /**
     * @author gaojun
     * @desc 查询oss上的所有文件
     * http://localhost:8080/file/list
     * @return List<OSSObjectSummary>
     * @Param
     */
    @RequestMapping("file/list")
    @ResponseBody
    public List<OSSObjectSummary> list()
            throws Exception {
        return this.fileUploadService.list();
    }
    /**
     * @author gaojun
     * @desc 根据文件名下载oss上的文件
     * http://localhost:8080/file/delete
     * @return ResponseEntity<byte[]>
     * @Param objectName
     */
    @RequestMapping("file/download")
    @ResponseBody
    public ResponseEntity<byte[]> download(@RequestParam("fileName") String objectName) throws IOException {
        HttpHeaders headers = new HttpHeaders();
//         以流的形式下载文件,这样可以实现任意格式的文件下载
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
//         文件名包含中文时乱码问题
//        headers.setContentDispositionFormData("attachment", new String(exportFile.getName().getBytes("utf-8"), "ISO8859-1"));
        headers.setContentDispositionFormData("attachment", objectName);
        InputStream is = this.fileUploadService.exportOssFile(objectName);
        return new ResponseEntity<byte[]>(is.toString().getBytes(),
                headers, HttpStatus.CREATED);
    }
}

5. 前端页面编写与测试

5.1 文件上传页面

使用ajax异步文件上传到后端对接的OSS上。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>oss文件上传</title>
    <script type="text/javascript" src="https://cdn.bootcss.com/jquery/1.11.2/jquery.js"></script>
    <script>
        function uploadfile() {
            $("#fileTypeError").html('');
            //获得文件名称
            var fileName = $('#file_upload').val();
            //截取文件类型,如(.jpg)                
            var fileType = fileName.substr(fileName.length - 4, fileName.length);
            if (fileType == '.bmp' || fileType == '.jpg' || fileType == '.jpeg' || fileType == '.gif' || fileType == '.png') {     //验证文件类型,此处验证也可使用正则
                $.ajax({
                    url: 'file/upload',//上传地址
                    type: 'POST',
                    cache: false,
                    data: new FormData($('#uploadForm')[0]),//表单数据
                    processData: false,
                    contentType: false,
                    success: function (rtn) {
                        if (rtn.status == 'error') {
                            $("#fileTypeError").html('*上传文件类型错误,支持类型:  .bmp .jpg .jpeg .gif .png');  //根据后端返回值,回显错误信息
                        } else {
                            $('div').append('<img src="' + rtn.name + '" style="width: 300px;height: 300px"></img>')
                        }
                    }
                });
            } else {
                $("#fileTypeError").html('*上传文件类型错误,支持类型: .bmp .jpg .jpeg .gif .png');
            }
        }
    </script>
</head>
<body>
<form id="uploadForm" enctype="multipart/form-data">  <!-- 声明文件上传 -->
    <input id="file_upload" type="file" name="file"/>  <!-- 定义change事件,选择文件后触发 -->
    <br/><span style="color: red" id="fileTypeError"></span>    <!-- 文件类型错误回显,此处通过前后端两次验证文件类型 -->
    <br/><input type="button" onclick="uploadfile()" value="上传">
</form>
<div></div>
</body>
</html>

效果展示:
在这里插入图片描述
在这里插入图片描述

5.2 文件管理页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>oss文件管理</title>
    <script type="text/javascript" src="https://cdn.bootcss.com/jquery/1.11.2/jquery.js"></script>
    <script type="text/javascript">
        var pre = 'https://gaojun-testbucket.oss-cn-shanghai.aliyuncs.com/';
        $(function () {
            listfile();
        });
        //文件列表
        function listfile() {
            $.ajax({
                url: "http://localhost:8080/file/list",
                type: 'POST',
                success: function (rtn) {
                    console.log(rtn.length);
                    for (var i = 0; i < rtn.length; i++) {
                        $('div').append('<img src="' + pre + rtn[i].key + '" style="width: 300px;height: 300px; padding: 10px" ondblclick="deletefile(this.src)" onclick="downloadfile(this.src)"></img>')
                    }
                }
            });
        }
        //文件下载
        function downloadfile(src) {
            var fileName = src.split(pre)[1];
            window.location.href = "http://localhost:8080/file/download?fileName=" + fileName;
        }
        //文件删除
        function deletefile(src) {
            var fileName = src.split(pre)[1];
            var param = {fileName: fileName};
            $.ajax({
                url: "http://localhost:8080/file/delete",
                data: param,
                success: function () {
                    alert('删除成功',fileName);
                    //删除页面
                    location.reload();
                }
            });
        }
    </script>
</head>
<body>
单击下载oss上的图片、双击删除oss上的图片<br>
<div>
</div>
</body>
</html>

效果展示:

刚才上传了一张照片,可以立马看到
在这里插入图片描述
单击页面即可下载图片
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/368064.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Ask林曦|来回答,30个你关心的日常问题(三)

在林曦老师的线上书法直播课上&#xff0c;上课前后的聊天时间里&#xff0c;时常有同学向林曦老师提问&#xff0c;这些问题涵盖了日常生活的诸多方面&#xff0c;从身体的保养&#xff0c;到快乐的法门&#xff0c;皆是大家感兴趣的&#xff0c;也都共同关切的。      暄…

Spring Cloud @RefreshScope 原理分析:扫描 Bean 定义

背景 最近读了一下 spring cloud 的 RefreshScope 生效的源码&#xff0c;总结一下该注解的 refresh 类型的类实例化的过程。 关键技术点&#xff1a; 扫描过程中对 RefreshScope 注解做了特殊处理&#xff0c;会额外注册两个BeanDefinition。GenericScope 实现了 BeanDefin…

医疗影像工具LEADTOOLS 入门教程: 从 PDF 中提取附件 - 控制台 C#

LEADTOOLS 是一个综合工具包的集合&#xff0c;用于将识别、文档、医疗、成像和多媒体技术整合到桌面、服务器、平板电脑、网络和移动解决方案中&#xff0c;是一项企业级文档自动化解决方案&#xff0c;有捕捉&#xff0c;OCR&#xff0c;OMR&#xff0c;表单识别和处理&#…

ARM平台搭建Python环境

ARM平台搭建Python环境写在最前常见问题1. 主机&#xff08;Ubuntu&#xff09;安装Python3.8.101.1 安装前的准备1.2 Ubuntu安装Python3.8.101.3 Ubuntu配置Python3.8.102. 宿主机&#xff08;AMR&#xff09;安装Python3.8.102.1 主机安装交叉编译工具2.2 交叉编译zlib库2.3 …

简析RE中python的exe文件

0x00. 前置学习 简单了解 python为什么要打包成exe文件&#xff1f;在日常生活中的应用是因为传输源文件以及源代码给他人是需要配置好一定的环境才能进行编译操作&#xff0c;而打包成exe文件就可以跟电脑软件一样打开就可以运行也可以分享给他人。 而对于ctf比赛来说&…

(三十三)大白话MySQL运行时多个事务同时执行是什么场景?

到目前为止&#xff0c;我们已经给大家深入讲解了MySQL的buffer pool机制、redo log机制和undo log机制&#xff0c;相信大家现在对我们平时执行一些增删改语句的实现原理&#xff0c;都有了一定较为深入的理解了&#xff01; 因为平时我们执行增删改的时候&#xff0c;无非就…

Python|Leetcode刷题日寄Part04

Python|Leetcode刷题日寄Part0401&#xff1a;环形链表02&#xff1a;跳跃游戏03&#xff1a;括号生成04&#xff1a;二分查找05&#xff1a;打家劫舍06&#xff1a;搜索旋转排序数组07&#xff1a;Z字形变换08&#xff1a;买卖股票的最佳时机Ⅱ09&#xff1a;最后一个单词的长…

国产蓝牙耳机300左右哪个牌子的好?三百左右蓝牙耳机推荐

现在的蓝牙耳机样式越来越五花八门&#xff0c;各种性能也越来越好。特别是国产蓝牙耳机&#xff0c;近几年的发展十分快速。那么&#xff0c;三百左右哪个牌子的国产蓝牙耳机好&#xff1f;接下来&#xff0c;我来给大家推荐几款三百左右的蓝牙耳机&#xff0c;一起来看看吧。…

Java加密算法:base64,MD5加密,对称加密,非对称加密

目录 Java&#xff1a;密码算法 1、base64加密方式 2、jdk原生api实现MD5 3、使用codec依赖实现MD5加密 4、SHA加密 5、MAC算法加密 6、对称加密 7、非对称加密 Java&#xff1a;密码算法 1、base64加密方式 public class demo {//设置编码格式private static final S…

搜索引擎的6个技巧

今天看了一期seo优化的视频&#xff0c;其中就有这么一篇关于百度搜索的几个小技巧&#xff0c;这里整理出来&#xff0c;分享给大家。不是标题党&#xff0c;真的99%的人都不知道这个6个小技巧。 搜索引擎一般都会有一些高级的搜索技巧&#xff0c;掌握这些技巧之后就可以过滤…

spring的启动过程(二) :springMvc的启动过程

在上一篇文章中&#xff0c;我们详解了spring的启动过程&#xff0c;这一篇介绍spring mvc的启动过程&#xff0c;那么spring和spring mvc有什么联系呢。 1.Spring和SpringMVC是父子容器关系。2.Spring整体框架的核心思想是容器&#xff0c;用来管理bean的生命周期&#xff0c;…

CAN总线开发一本全(3) - 微控制器集成的FlexCAN外设

CAN总线开发一本全&#xff08;3&#xff09; - 微控制器集成的FlexCAN外设 苏勇&#xff0c;2023年2月 文章目录CAN总线开发一本全&#xff08;3&#xff09; - 微控制器集成的FlexCAN外设引言硬件外设模块系统概要总线接口单元 - 寄存器清单数据结构 - 消息缓冲区MB初始化过…

taobao.top.oaid.merge( OAID订单合并 )

&#xffe5;开放平台免费API必须用户授权 基于OAID&#xff08;收件人ID&#xff0c; Open Addressee ID)做订单合并&#xff0c;确保相同收件人信息的订单合并到相同组。 公共参数 请求地址: HTTP地址 http://gw.api.taobao.com/router/rest 公共请求参数: 公共响应参数: 请…

win10环境下安装java开发环境安装java

一&#xff1a;环境介绍 安装系统版本&#xff1a;win10 java版本&#xff1a;java SE 17 二&#xff1a;下载Java安装包 官网下载Java安装包&#xff1a;Java Downloads | Oracle 中国 选择需要的Java版本进行下载&#xff0c;如果没有要选择的版本&#xff0c;可以选择最新…

称重传感器差分输入信号隔离转换直流放大变送器0-±10mV/0-±20mV转0-10V/4-20mA

主要特性DIN11 IPO 压力应变桥信号处理系列隔离放大器是一种将差分输入信号隔离放大、转换成按比例输出的直流信号导轨安装变送模块。产品广泛应用在电力、远程监控、仪器仪表、医疗设备、工业自控等行业。此系列模块内部嵌入了一个高效微功率的电源&#xff0c;向输入端和输出…

(二十九)大白话MySQL直接强行把redo log写入磁盘?

上一讲我们给大家说了一下redo log block这个概念&#xff0c;大家现在都知道平时我们执行完增删改之后&#xff0c;要写入磁盘的redo log&#xff0c;其实应该是先进入到redo log block这个数据结构里去的&#xff0c;然后再进入到磁盘文件里&#xff0c;如下图所示。 那么今天…

三、锁相关知识

文章目录锁的分类可重入锁、不可重入锁乐观锁、悲观锁公平锁、非公平锁互斥锁、共享锁深入synchronized类锁、对象锁synchronized的优化synchronized实现原理synchronized的锁升级重量锁底层ObjectMonitor深入ReentrantLockReentrantLock和synchronized的区别AQS概述加锁流程源…

Flink中遇到的问题

目录 1、提交flink 批处理任务时遇到的问题 2、flink定时任务&#xff0c;mysql连接超时问题 3、yarn 增加并行任务数量配置 4、flink checkpoint 恢复失败 5、flink程序在hadoop集群跑了一段时间莫名挂掉 1、提交flink 批处理任务时遇到的问题 问题描述&#xff1a; …

超详细树状数组讲解(+例题:动态求连续区间和)

树状数组的作用&#xff1a;快速的对数列的一段范围求和快速的修改数列的某一个数为什么要使用树状数组&#xff1a;大家从作用中看到快速求和的时候可能会想到为什么不使用前缀和只需要预处理一下就可以在O(1)的时间复杂度下实行对于数列的一段范围的和但是我们可以得到当我们…

记一次服务器入侵事件的应急响应

0x01 事件背景 8月某日&#xff0c;客户官网被黑&#xff0c;需在特定时间内完成整改。为避免客户业务受到影响&#xff0c;实验室相关人员第一时间展开本次攻击事件的应急处理。 0x02 事件分析 网站源码被篡改&#xff0c;攻击者一定获取到了权限&#xff0c;那么接下来的思…