• Day88.七牛云: 房源图片、用户头像上传


    目录

    一、七牛云存储

    4.鉴权

     二、开发者中心,上传、删除测试

    1.添加依赖

    2.代码测试 

    3. 封装工具类

    三、房源图片上传

    1. spring mvc 配置上传支持

    2. house/show.html页面添加事件

    3.添加服务器端代码

    4. 上传页面

    四、用户头像上传

    1、用户列表页添加选项

    2、添加服务器端代码

    3、上传页面


    在实际开发中,我们会有很多处理不同功能的服务器。例如:

    应用服务器:负责部署我们的应用

    数据库服务器:运行我们的数据库

    文件服务器:负责存储用户上传文件的服务器

    分服务器处理的目的是让服务器各司其职,从而提高我们项目的运行效率。

    常见的图片存储方案:

    方案一:使用nginx搭建图片服务器

    方案二:使用开源的分布式文件存储系统,例如Fastdfs、HDFS等

    方案三:使用云存储,例如阿里云、==七牛云==等

    一、七牛云存储

    七牛云(隶属于上海七牛信息技术有限公司)是国内领先的以视觉智能和数据智能为核心的企业级云计算服务商,同时也是国内知名智能视频云服务商,累计为 70 多万家企业提供服务,覆盖了国内80%网民。围绕富媒体场景推出了对象存储、融合 CDN 加速、容器云、大数据平台、深度学习平台等产品、并提供一站式智能视频云解决方案。为各行业及应用提供可持续发展的智能视频云生态,帮助企业快速上云,创造更广阔的商业价值。

    官网:七牛云 - 国内领先的企业级云服务商

    1.注册、登录

    要使用七牛云的服务,首先需要注册成为会员。地址:七牛云开发者平台

    2.新建存储空间

     3.查看存储空间信息

    4.鉴权

    Java SDK的所有的功能,都需要合法的授权。授权凭证的签算需要七牛账号下的一对==有效的Access Key和Secret Key==,这对密钥可以在七牛云管理控制台的个人中心(七牛云开发者平台)获得,如下图:

     二、开发者中心,上传、删除测试

    可以通过七牛云提供的开发者中心学习如何操作七牛云服务,代码测试

    地址:七牛开发者中心

    1.添加依赖

    shf-parent添加依赖管理

    1. <!--七牛云服务平台,第三方服务(图片上传)-->
    2. <dependency>
    3. <groupId>com.qiniu</groupId>
    4. <artifactId>qiniu-java-sdk</artifactId>
    5. <version>7.2.0</version>
    6. </dependency>

    common-util引入依赖  

    1. <!--七牛云服务平台,第三方服务(图片上传)-->
    2. <dependency>
    3. <groupId>com.qiniu</groupId>
    4. <artifactId>qiniu-java-sdk</artifactId>
    5. </dependency>

    2.代码测试 

    1. package com.atguigu.test;
    2. import com.google.gson.Gson;
    3. import com.qiniu.common.QiniuException;
    4. import com.qiniu.common.Zone;
    5. import com.qiniu.http.Response;
    6. import com.qiniu.storage.BucketManager;
    7. import com.qiniu.storage.Configuration;
    8. import com.qiniu.storage.UploadManager;
    9. import com.qiniu.storage.model.DefaultPutRet;
    10. import com.qiniu.util.Auth;
    11. import org.junit.Test;
    12. public class TestQiniu {
    13. // 上传本地文件
    14. @Test
    15. public void uploadFile(){
    16. //构造一个带指定Zone对象的配置类
    17. Configuration cfg = new Configuration(Zone.zone2());
    18. //...其他参数参考类注释
    19. UploadManager uploadManager = new UploadManager(cfg);
    20. //...生成上传凭证,然后准备上传
    21. String accessKey = "***";
    22. String secretKey = "***";
    23. String bucket = "shf-img1";
    24. //如果是Windows情况下,格式是 D:\\qiniu\\test.png,可支持中文
    25. String localFilePath = "C:/Users/Plisetsky/Pictures/Saved Pictures/test.jpg";
    26. //默认不指定key的情况下,以文件内容的hash值作为文件名
    27. String key = "test.jpg";
    28. Auth auth = Auth.create(accessKey, secretKey);
    29. String upToken = auth.uploadToken(bucket);
    30. try {
    31. Response response = uploadManager.put(localFilePath, key, upToken);
    32. //解析上传成功的结果
    33. DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
    34. System.out.println(putRet.key);
    35. System.out.println(putRet.hash);
    36. } catch (QiniuException ex) {
    37. Response r = ex.response;
    38. System.err.println(r.toString());
    39. try {
    40. System.err.println(r.bodyString());
    41. } catch (QiniuException e) {
    42. e.printStackTrace();
    43. }
    44. }
    45. }
    46. // 删除空间中的文件
    47. @Test
    48. public void deleteFile() {
    49. //构造一个带指定Zone对象的配置类
    50. Configuration cfg = new Configuration(Zone.zone2());
    51. //...其他参数参考类注释
    52. String accessKey = "***";
    53. String secretKey = "***";
    54. String bucket = "shf-img1";//空间
    55. String key = "test.jpg";//文件名称
    56. Auth auth = Auth.create(accessKey, secretKey);
    57. BucketManager bucketManager = new BucketManager(auth, cfg);
    58. try {
    59. bucketManager.delete(bucket, key);
    60. } catch (QiniuException ex) {
    61. //如果遇到异常,说明删除失败
    62. System.err.println(ex.code());
    63. System.err.println(ex.response.toString());
    64. }
    65. }
    66. }

    3. 封装工具类

    1. package com.atguigu.util;
    2. import com.google.gson.Gson;
    3. import com.qiniu.common.QiniuException;
    4. import com.qiniu.common.Zone;
    5. import com.qiniu.http.Response;
    6. import com.qiniu.storage.BucketManager;
    7. import com.qiniu.storage.Configuration;
    8. import com.qiniu.storage.UploadManager;
    9. import com.qiniu.storage.model.DefaultPutRet;
    10. import com.qiniu.util.Auth;
    11. /**
    12. * 七牛云工具类
    13. */
    14. public class QiniuUtils {
    15. //设置ak,sk
    16. public static String accessKey = "***";
    17. public static String secretKey = "***";
    18. public static String bucket = "shf-img1";
    19. public static void upload2Qiniu(String filePath,String fileName){
    20. //构造一个带指定Zone对象的配置类
    21. Configuration cfg = new Configuration(Zone.zone2());
    22. UploadManager uploadManager = new UploadManager(cfg);
    23. Auth auth = Auth.create(accessKey, secretKey);
    24. String upToken = auth.uploadToken(bucket);
    25. try {
    26. Response response = uploadManager.put(filePath, fileName, upToken);
    27. //解析上传成功的结果
    28. DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
    29. } catch (QiniuException ex) {
    30. Response r = ex.response;
    31. try {
    32. System.err.println(r.bodyString());
    33. } catch (QiniuException ex2) {
    34. //ignore
    35. }
    36. }
    37. }
    38. //上传文件
    39. public static void upload2Qiniu(byte[] bytes, String fileName){
    40. //构造一个带指定Zone对象的配置类
    41. Configuration cfg = new Configuration(Zone.zone2());
    42. //...其他参数参考类注释
    43. UploadManager uploadManager = new UploadManager(cfg);
    44. //默认不指定key的情况下,以文件内容的hash值作为文件名
    45. String key = fileName;
    46. Auth auth = Auth.create(accessKey, secretKey);
    47. String upToken = auth.uploadToken(bucket);
    48. try {
    49. Response response = uploadManager.put(bytes, key, upToken);
    50. //解析上传成功的结果
    51. DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
    52. System.out.println(putRet.key);
    53. System.out.println(putRet.hash);
    54. } catch (QiniuException ex) {
    55. Response r = ex.response;
    56. System.err.println(r.toString());
    57. try {
    58. System.err.println(r.bodyString());
    59. } catch (QiniuException ex2) {
    60. //ignore
    61. }
    62. }
    63. }
    64. //删除文件
    65. public static void deleteFileFromQiniu(String fileName){
    66. //构造一个带指定Zone对象的配置类
    67. Configuration cfg = new Configuration(Zone.zone2());
    68. String key = fileName;
    69. Auth auth = Auth.create(accessKey, secretKey);
    70. BucketManager bucketManager = new BucketManager(auth, cfg);
    71. try {
    72. bucketManager.delete(bucket, key);
    73. } catch (QiniuException ex) {
    74. //如果遇到异常,说明删除失败
    75. System.err.println(ex.code());
    76. System.err.println(ex.response.toString());
    77. }
    78. }
    79. }

    三、房源图片上传

    1. spring mvc 配置上传支持

    在spring-mvc添加配置

    1. <!--配置上传解析器
    2. "maxUploadSize":表示文件大小,图片的大小
    3. "maxInMemorySize" :图片加载到内存当中的大小 长 * 宽 * 像素字节数(argb8888,rgb565,argb4444)
    4. "defaultEncoding":UTF-8
    5. 优秀程序员:CV战士
    6. -->
    7. <bean id="multipartResolver"
    8. class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    9. <!-- 设定文件上传的最大值为100MB,100*1024*1024 -->
    10. <property name="maxUploadSize" value="104857600" />
    11. <!-- 设定文件上传时写入内存的最大值,如果小于这个参数不会生成临时文件,默认为10240 -->
    12. <property name="maxInMemorySize" value="4096" />
    13. <!-- 设定默认编码 -->
    14. <property name="defaultEncoding" value="UTF-8"/>
    15. </bean>

    2. house/show.html页面添加事件

    1. $(function(){
    2. //表示房源图片
    3. $("#upload1").on("click",function(){
    4. opt.openWin('/houseImage/uploadShow/[[${house.id}]]/1','上传房源图片',580,430);
    5. });
    6. //表示房产图片
    7. $("#upload2").on("click",function(){
    8. opt.openWin('/houseImage/uploadShow/[[${house.id}]]/2','上传房产图片',580,430);
    9. });
    10. //上传首页默认图片
    11. $("#upload3").on("click",function(){
    12. opt.openWin('/houseImage/uploadShow/[[${house.id}]]/3','上传首页默认图片',580,430);
    13. });
    1. <div class="row">
    2. <div class="col-sm-12">
    3. <div class="ibox float-e-margins">
    4. <div class="ibox-title">
    5. <h3>房源图片信息</h3>
    6. <a class="btn btn-xs btn-primary" id="upload1">上传房源图片</a>
    7. </div>
    8. <div class="ibox-content">
    9. <a th:each="item,it : ${houseImage1List}" class="fancybox" >
    10. <img alt="image" th:src="${item.imageUrl}"/>
    11. <a th:attr="data-id=${item.id}" class="deleteImages1">删除</a>
    12. </a>
    13. </div>
    14. </div>
    15. </div>
    16. </div>
    17. <div class="row">
    18. <div class="col-sm-12">
    19. <div class="ibox float-e-margins">
    20. <div class="ibox-title">
    21. <h3>房产图片信息</h3>
    22. <a class="btn btn-xs btn-primary" id="upload2">上传房产图片</a>
    23. </div>
    24. <div class="ibox-content">
    25. <a th:each="item,it : ${houseImage2List}" class="fancybox" >
    26. <img alt="image" th:src="${item.imageUrl}"/>
    27. <a th:attr="data-id=${item.id}" class="deleteImages1">删除</a>
    28. </a>
    29. </div>
    30. </div>
    31. </div>
    32. </div>
    33. <div class="row">
    34. <div class="col-sm-12">
    35. <div class="ibox float-e-margins">
    36. <div class="ibox-title">
    37. <h3>房源首页图片</h3>
    38. <a class="btn btn-xs btn-primary" id="upload3">上传首页默认图片</a>
    39. </div>
    40. <div class="ibox-content">
    41. <a th:each="item,it : ${houseImage3List}" class="fancybox" >
    42. <img alt="image" th:src="${item.imageUrl}"/>
    43. <a th:attr="data-id=${item.id}" class="deleteImages2">删除</a>
    44. </a>
    45. </div>
    46. </div>
    47. </div>
    48. </div>

    3.添加服务器端代码

    1. package com.atguigu.controller;
    2. import com.alibaba.dubbo.config.annotation.Reference;
    3. import com.atguigu.entity.HouseImage;
    4. import com.atguigu.result.Result;
    5. import com.atguigu.service.HouseImageService;
    6. import com.atguigu.util.QiniuUtils;
    7. import org.springframework.stereotype.Controller;
    8. import org.springframework.web.bind.annotation.PathVariable;
    9. import org.springframework.web.bind.annotation.RequestMapping;
    10. import org.springframework.web.bind.annotation.RequestParam;
    11. import org.springframework.web.bind.annotation.ResponseBody;
    12. import org.springframework.web.multipart.MultipartFile;
    13. import java.util.Map;
    14. import java.util.UUID;
    15. /**
    16. * @Date 2022/6/22 14:12
    17. * @Author by:Plisetsky
    18. */
    19. @Controller
    20. @RequestMapping("/houseImage")
    21. public class HouseImageController {
    22. private static final String PAGE_UPLOAD_SHOW = "house/upload";
    23. private static final String ACTION_LIST = "redirect:/house/detail/";
    24. @Reference
    25. HouseImageService houseImageService;
    26. //删除默认展示图片
    27. @RequestMapping("/deleteDefault/{houseId}/{id}")
    28. public String deleteDefault(@PathVariable("houseId")Long houseId,@PathVariable("id") Long id) {
    29. HouseImage houseImage = houseImageService.getById(id);
    30. String imageName = houseImage.getImageName();
    31. houseImageService.delete(id);//删除前查询数据,否则删除后查不到了
    32. //删除house默认图片
    33. houseImageService.updateDefaultImage(houseId,null);
    34. //删除七牛云内图片
    35. QiniuUtils.deleteFileFromQiniu(imageName);
    36. return ACTION_LIST + houseId;
    37. }
    38. //删除房源、房产图片
    39. @RequestMapping("/delete/{houseId}/{id}")
    40. public String delete(@PathVariable("houseId")Long houseId,@PathVariable("id") Long id){
    41. HouseImage houseImage = houseImageService.getById(id);
    42. String imageName = houseImage.getImageName();
    43. houseImageService.delete(id);//删除前查询数据,否则删除后查不到了
    44. //删除七牛云内图片
    45. QiniuUtils.deleteFileFromQiniu(imageName);
    46. return ACTION_LIST + houseId;
    47. }
    48. //上传房源、房产图片,可以不返回值
    49. @RequestMapping("/upload/{houseId}/{type}")
    50. @ResponseBody
    51. public Result upload(@RequestParam("file") MultipartFile[] files, //file是固定的,底层会自动生成表单项.[]接收多个表单项
    52. @PathVariable("houseId") Long houseId,
    53. @PathVariable("type") Integer type) throws Exception { //接收上传文件,再上传到七牛云上
    54. if(files !=null && files.length>0){ //至少上传一个文件
    55. for (MultipartFile file:files){
    56. byte[] bytes = file.getBytes();
    57. //String name = file.getOriginalFilename();//原始文件名称
    58. //QiniuUtils.upload2Qiniu(bytes,name); 不能使用原始文件名称上传,会重名覆盖
    59. String newFileName = UUID.randomUUID().toString();
    60. //将图片上传到七牛云
    61. QiniuUtils.upload2Qiniu(bytes,newFileName);
    62. String imageUrl = "http://rdv0p81lw.hn-bkt.clouddn.com/"+newFileName;
    63. //如果上传的是首页默认图片,将地址更新到house表
    64. if(type==3){
    65. houseImageService.updateDefaultImage(houseId,imageUrl);
    66. }
    67. //将图片路径信息等保存到数据库
    68. HouseImage houseImage = new HouseImage();
    69. houseImage.setHouseId(houseId);
    70. houseImage.setImageName(newFileName);
    71. houseImage.setImageUrl(imageUrl);
    72. houseImage.setType(type);
    73. houseImageService.insert(houseImage);
    74. }
    75. }
    76. return Result.ok();
    77. }
    78. //前往上传页面
    79. @RequestMapping("/uploadShow/{houseId}/{type}")
    80. public String uploadShow(@PathVariable("houseId") Long houseId,
    81. @PathVariable("type") Integer type, Map map){
    82. map.put("houseId",houseId);
    83. map.put("type",type);
    84. return PAGE_UPLOAD_SHOW;
    85. }
    86. }

    4. 上传页面

    1. <!DOCTYPE html>
    2. <html xmlns:th="http://www.thymeleaf.org">
    3. <head th:include="common/head :: head"></head>
    4. <!--百度上传组件-->
    5. <link rel="stylesheet" type="text/css" th:href="@{/static/css/plugins/webuploader/webuploader.css}">
    6. <link rel="stylesheet" type="text/css" th:href="@{/static/css/demo/webuploader-demo.css}">
    7. <script th:src="@{/static/js/plugins/webuploader/webuploader.min.js}"></script>
    8. <script th:src="@{/static/js/demo/webuploader-demo.js}"></script>
    9. <script type="text/javascript">
    10. // 添加全局站点信息 swf文件路径
    11. var BASE_URL = '/static/js/plugins/webuploader';
    12. // 自定义请求地址,传入房子id和类型
    13. var BASE_UPLOAD = '/houseImage/upload/[[${houseId}]]/[[${type}]]';
    14. // 会自动生成表单
    15. </script>
    16. <body class="gray-bg">
    17. <div class="row">
    18. <div class="col-sm-9">
    19. <div class="wrapper wrapper-content animated fadeInUp">
    20. <div class="ibox">
    21. <div class="ibox-content">
    22. <div class="row">
    23. <div class="ibox-content">
    24. <div class="page-container" id="uploadShow">
    25. <p>您可以尝试文件拖拽,使用QQ截屏工具,然后激活窗口后粘贴,或者点击添加图片按钮,来体验此demo.</p>
    26. <div id="uploader" class="wu-example">
    27. <div class="queueList">
    28. <div id="dndArea" class="placeholder">
    29. <div id="filePicker"></div>
    30. <p>或将照片拖到这里,单次最多可选300张</p>
    31. </div>
    32. </div>
    33. <div class="statusBar" style="display:none;">
    34. <div class="progress">
    35. <span class="text">0%</span>
    36. <span class="percentage"></span>
    37. </div>
    38. <div class="info"></div>
    39. <div class="btns">
    40. <div id="filePicker2"></div>
    41. <div class="uploadBtn">开始上传</div>
    42. </div>
    43. </div>
    44. </div>
    45. </div>
    46. </div>
    47. </div>
    48. <div class="row">
    49. <div class="col-sm-4 col-sm-offset-2">
    50. <button class="btn btn-primary" type="button" onclick="opt.closeWin(true);">确定</button>
    51. </div>
    52. </div>
    53. </div>
    54. </div>
    55. </div>
    56. </div>
    57. </div>
    58. </body>
    59. </html>

    5. 上传测试

    四、用户头像上传

    1、用户列表页添加选项

    <a class="upload" th:attr="data-id=${item.id}">上传头像</a>
    1. $(".upload").on("click",function(){
    2. var id = $(this).attr("data-id");
    3. opt.openWin('/admin/uploadShow/'+id,'上传头像',580,300);
    4. });

    2、添加服务器端代码

    1. //头像上传
    2. @RequestMapping("/upload/{id}")
    3. public String upload(@PathVariable("id") Long id,
    4. @PathVariable("file") MultipartFile file,HttpServletRequest request) throws IOException {
    5. //1.上传到七牛云
    6. byte[] bytes = file.getBytes();
    7. String newFileName = UUID.randomUUID().toString();
    8. QiniuUtils.upload2Qiniu(bytes,newFileName);
    9. //2.地址存储到数据库
    10. String imageUrl = "你的七牛云空间的域名/"+newFileName;
    11. Admin admin = new Admin();
    12. admin.setId(id);
    13. admin.setHeadUrl(imageUrl);
    14. adminService.update(admin);
    15. return this.successPage(this.MESSAGE_SUCCESS, request);
    16. }
    17. //前往头像上传
    18. @RequestMapping("/uploadShow/{id}")
    19. public String uploadShow(@PathVariable("id") Long id,Map map){
    20. map.put("id",id);
    21. return PAGE_UPLOAD;
    22. }

    3、上传页面

    admin/upload.html

    1. <!DOCTYPE html>
    2. <html xmlns:th="http://www.thymeleaf.org">
    3. <head th:include="common/head :: head"></head>
    4. <body class="gray-bg">
    5. <div class="wrapper wrapper-content animated fadeInRight">
    6. <div class="ibox float-e-margins">
    7. <div class="ibox-content" style="width: 98%;">
    8. <form id="ec" th:action="@{/admin/upload/{id}(id=${id})}" method="post" enctype="multipart/form-data" class="form-horizontal">
    9. <div class="form-group">
    10. <label class="col-sm-2 control-label">上传头像:</label>
    11. <div class="col-sm-10">
    12. <input type="file" name="file" id="file" class="form-control" readonly/>
    13. </div>
    14. </div>
    15. <div class="hr-line-dashed"></div>
    16. <div class="form-group">
    17. <div class="col-sm-4 col-sm-offset-2 text-right">
    18. <button class="btn btn-primary" type="submit">确定</button>
    19. <button class="btn btn-white" type="button" onclick="javascript:opt.closeWin();" value="取消">取消</button>
    20. </div>
    21. </div>
    22. </form>
    23. </div>
    24. </div>
    25. </div>
    26. </body>
    27. </html>

  • 相关阅读:
    Leetcode刷题【hot100】最长连续序列
    【C++笔试强训】第二十七天
    Python万圣节蝙蝠
    python读取图像小工具
    【技术开发】酒精测试仪解决方案开发设计
    MySQL夺命66问,面试必看!(荣耀典藏版)
    软件测试逻辑覆盖相关理解
    【Python 零基础入门】常用内置函数 再探
    Mybatis-plus 使用
    腾讯云服务器mysql安装
  • 原文地址:https://blog.csdn.net/a111042555/article/details/125484823