侧边栏壁纸
博主头像
落叶人生博主等级

走进秋风,寻找秋天的落叶

  • 累计撰写 130562 篇文章
  • 累计创建 28 个标签
  • 累计收到 9 条评论
标签搜索

目 录CONTENT

文章目录

SpringBoot实现azure blob的文件上传

2022-06-13 星期一 / 0 评论 / 0 点赞 / 109 阅读 / 26277 字

Azure Blob 存储是 Microsoft 提供的适用于云的对象存储解决方案。 Blob 存储最适合存储巨量的非结构化数据准备Azure 订阅点击创建免费帐户,选择免费开始,使用微软账户注册订阅

.

Azure Blob 存储是 Microsoft 提供的适用于云的对象存储解决方案。 Blob 存储最适合存储巨量的非结构化数据

.

准备

Azure 订阅

点击创建免费帐户,选择免费开始,使用微软账户注册订阅后即可试用12个月

Azure 存储帐户

点击创建存储帐户,根据教程即可创建一个存储账户,若没有安装azure cli,推荐直接参考【门户网站】一栏

Azure门户凭据

  1. 登录到 Azure 门户
  2. 找到自己的存储帐户。
  3. 在存储帐户概述的“设置”部分,选择“访问密钥”。 在这里,可以查看你的帐户访问密钥以及每个密钥的完整连接字符串。
  4. 找到“密钥 1”下面的“连接字符串”值,选择“复制”按钮复制该连接字符串。 下一步需将此连接字符串值添加到某个环境变量。

开发步骤

配置

  • 引入依赖
<!--lombok --><dependency>   <groupId>org.projectlombok</groupId>   <artifactId>lombok</artifactId>   <optional>true</optional></dependency><!--azure storage --><dependency>    <groupId>com.microsoft.azure</groupId>    <artifactId>azure-storage-spring-boot-starter</artifactId>    <version>0.2.0</version></dependency>
  • 属性配置
spring:  servlet:  	    multipart:	# spring mvc文件上传      max-request-size: 10MB      max-file-size: 1MBazure:  storage: # azure储存配置    default-endpoints-protocol: https    account-name: [account-name]    account-key: [account-key]    endpoint-suffix: [endpoint-suffix]    container-reference: [container-reference]	# 容器名称    generate-thumbnail: false  # 生成缩略图

代码编写

  • 根据属性编写对应参数类
@Data@Componentpublic class AzureStorageParam {    @Value("${azure.storage.default-endpoints-protocol}")    private String defaultEndpointsProtocol;    @Value("${azure.storage.account-name}")    private String accountName;    @Value("${azure.storage.account-key}")    private String accountKey;    @Value("${azure.storage.endpoint-suffix}")    private String endpointSuffix;    @Value("${azure.storage.container-reference}")    private String containerReference;    /**     * 拼接连接字符串     */    public String getStorageConnectionString() {        String storageConnectionString =            String.format("DefaultEndpointsProtocol=%s;AccountName=%s;AccountKey=%s;EndpointSuffix=%s",                defaultEndpointsProtocol, accountName, accountKey, endpointSuffix);        return storageConnectionString;    }}
  • 编写文件上传的返回模型
@Data@Accessors(chain = true)public class BlobUpload {    // 文件名    private String fileName;    // 原文件    private String fileUrl;    // 缩略图    private String thumbnailUrl;}
  • 工具类
/** * 获取blob container *  * @param storageConnectionString * @param containerReference * @return */public static CloudBlobContainer getAzureContainer(String storageConnectionString, String containerReference) {    CloudStorageAccount storageAccount;    CloudBlobClient blobClient = null;    CloudBlobContainer container = null;    try {        storageAccount = CloudStorageAccount.parse(storageConnectionString);        blobClient = storageAccount.createCloudBlobClient();        container = blobClient.getContainerReference(containerReference);        container.createIfNotExists(BlobContainerPublicAccessType.CONTAINER, new BlobRequestOptions(),            new OperationContext());        return container;    } catch (Exception e) {        logger.error("获取azure container异常: [{}]" , e.getMessage());    }    return null;}
  • 编写文件上传的业务层接口
public interface IAzureStorageService {    /**     * 上传文件(图片)     * @param type 文件类型     * @param multipartFiles 文件     * @return     */    BaseResult<Object> uploadFile(String type, MultipartFile[] multipartFiles);}
  • 实现类
@Servicepublic class AzureStorageServiceImpl implements IAzureStorageService {    // 设置缩略图的宽高    private static int thumbnailWidth = 150;    private static int thumbnailHeight = 100;    private static String thumbnailPrefix = "mini_";    private static String originPrefix = "FAQ_";    private final Logger logger = LoggerFactory.getLogger(AzureStorageServiceImpl.class);    @Value("{azure.storage.generate-thumbnail}")    private String generateThumbnail;    @Autowired    private AzureStorageParam azureStorageParam;    @Override    public BaseResult<Object> uploadFile(String type, MultipartFile[] multipartFiles) {        // 校验图片        if (hasInvalidPic(multipartFiles)) {            return BaseResult.error("包含非法图片格式");        }        List<BlobUpload> blobUploadEntities = new ArrayList<>();        // 获取blob容器        CloudBlobContainer container = AzureStorageUtil.getAzureContainer(            azureStorageParam.getStorageConnectionString(), azureStorageParam.getContainerReference());        if (container == null) {            logger.error("获取azure container异常");            return BaseResult.error("获取容器失败");        }        try {            for (MultipartFile tempMultipartFile : multipartFiles) {                try {                    // 将 blob 上传到容器                    String contentType = tempMultipartFile.getContentType().toLowerCase();                    if (!contentType.equals("image/jpg") && !contentType.equals("image/jpeg")                        && !contentType.equals("image/png")) {                        return BaseResult.error("not pic");                    }                    // 时间+随机数+文件扩展名                    String picType = contentType.split("/")[1];                    String timeStamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));                    int number = (int)((Math.random() * 9) * 1000);                    String referenceName = originPrefix + timeStamp + number + "." + picType;                    CloudBlockBlob blob = container.getBlockBlobReference(referenceName);                    blob.getProperties().setContentType(tempMultipartFile.getContentType());                    blob.upload(tempMultipartFile.getInputStream(), tempMultipartFile.getSize());                    // 返回图片URL                    BlobUpload blobUploadEntity = new BlobUpload();                    blobUploadEntity.setFileName(tempMultipartFile.getOriginalFilename())                        .setFileUrl(blob.getUri().toString());                    // 生成缩略图                    if ("true".equalsIgnoreCase(generateThumbnail)) {                        BufferedImage img =                            new BufferedImage(thumbnailWidth, thumbnailHeight, BufferedImage.TYPE_INT_RGB);                        BufferedImage read = ImageIO.read(tempMultipartFile.getInputStream());                        img.createGraphics().drawImage(                            read.getScaledInstance(thumbnailWidth, thumbnailHeight, Image.SCALE_SMOOTH), 0, 0, null);                        ByteArrayOutputStream baos = new ByteArrayOutputStream();                        ImageIO.write(img, "jpg", baos);                        InputStream bais = new ByteArrayInputStream(baos.toByteArray());                        String blobThumbnail = originPrefix + thumbnailPrefix + timeStamp + number + ".jpg";                        CloudBlockBlob thumbnailBlob = container.getBlockBlobReference(blobThumbnail);                        thumbnailBlob.getProperties().setContentType("image/jpeg");                        thumbnailBlob.upload(bais, baos.toByteArray().length);                        blobUploadEntity.setFileUrl(blob.getUri().toString())                            .setThumbnailUrl(thumbnailBlob.getUri().toString());                        // 关闭流                        baos.close();                        bais.close();                    }                    blobUploadEntities.add(blobUploadEntity);                } catch (Exception e) {                    logger.error("上传[{}]时出现异常:[{}]", tempMultipartFile.getOriginalFilename(), e.getMessage());                    return BaseResult.error("上传出现异常,请稍后再试");                }            }            return BaseResult.success(blobUploadEntities);        } catch (Exception e) {            logger.error("上传文件出现异常: [{}]", e.getMessage());        }        return BaseResult.error("上传出现异常,请稍后再试");    }    /**     * 判断批量文件中是否都为图片     */    private boolean hasInvalidPic(MultipartFile[] multipartFiles) {        List<String> picTypeList = Arrays.asList("image/jpg", "image/jpeg", "image/png");        return Arrays.stream(multipartFiles).anyMatch(i -> !picTypeList.contains(i.getContentType().toLowerCase()));    }}
  • mvc控制器
@RestControllerpublic class UploadController {    private static final Logger logger = LoggerFactory.getLogger(UploadController.class);    @Autowired    AzureStorageServiceImpl azureStorageService;    /**     * 文件上传(图片)     *      * @param multipartFiles     * @return     */    @PostMapping("/upload")    public BaseResult<Object> upload(@RequestPart("file") MultipartFile[] multipartFiles) {        logger.info("开始文件上传...");        if (multipartFiles == null || multipartFiles.length == 0) {            return BaseResult.error("上传失败,请选择文件");        }        return azureStorageService.uploadFile("PICTURE", multipartFiles);    }}

实列测试

使用postman测试

【请求体】-【form-data】-【key=file】,然后从本地选择若干图片

  • 复制图片url即可查看图片

  • 查看blob容器,即可以看到最新上传的文件

使用表单提交测试

为方便测试,直接使用thymeleaf模板进行页面上传

  • 引入依赖
<!-- thymeleaf --><dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-thymeleaf</artifactId></dependency>
  • 简易页面
<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>多文件上传</title></head><body><form method="post" action="/upload" enctype="multipart/form-data">    <input type="file" name="file"><br>    <input type="file" name="file"><br>    <input type="file" name="file"><br>    <input type="submit" value="提交"></form></body></html>
  • 控制器添加跳转请求
@Controllerpublic class UploadController {    private static final Logger logger = LoggerFactory.getLogger(UploadController.class);    @Autowired    AzureStorageServiceImpl azureStorageService;    /**     * 文件上传,跳转使用     */    @GetMapping("/upload")    public String upload() {        return "upload";    }    /**     * 文件上传(图片)     */    @PostMapping("/upload")    @ResponseBody    public BaseResult<Object> upload(@RequestPart("file") MultipartFile[] multipartFiles) {        logger.info("开始文件上传...");        if (multipartFiles == null || multipartFiles.length == 0) {            return BaseResult.error("上传失败,请选择文件");        }        return azureStorageService.uploadFile("PICTURE", multipartFiles);    }}
  • 浏览器访问http://localhost:8082/upload,选择图片上传

  • 上传成功


详细过程,可参考源代码:github.com/chetwhy/clo…


参考文章:

Azure Blob 存储文档

Spring Boot实战之文件上传存入Azure Storage

.
.

广告 广告

评论区