翼度科技»论坛 编程开发 mysql 查看内容

关于MySQL存取图片的三种方式(含源码示例)

8

主题

8

帖子

24

积分

新手上路

Rank: 1

积分
24
Method1:采用BLOB数据格式存图片。
其实这种方式很不合理,数据库大小会激增会导致简单的查询都及其缓慢。
Method2:采用文本格式存储图片。
虽然也不怎么合理,因为关系型数据库本身就不太适合存巨长的大数据量的东西。
但是由于只涉及到base64加密和解码,且可以都写入后台部分,减轻前端负担。
Method3:将图片单独存放在某个服务器上,数据库只存放他们的url地址。
最高效也是最常用的方法。
后面有展示两种示例。

详细代码示例


Method1详细代码示例:

由于目前做的这个项目,同学A之前一直使用的这种方式将文件中的图片读取到数据库表,所以我只写了对BloB类型图片的取数据部分的代码。且过程较繁琐,可用性不强,就不贴了。
这个代码是A给我发的,实在太久了,她也忘了出处了。有人知道请艾特我一下,我标上链接。
  1. package org.springboot.wechatcity.utill;

  2. import java.io.FileInputStream;
  3. import java.io.FileOutputStream;
  4. import java.io.InputStream;
  5. import java.io.OutputStream;
  6. import java.sql.Blob;
  7. import java.sql.Connection;
  8. import java.sql.PreparedStatement;
  9. import java.sql.ResultSet;

  10. /**
  11. * 存入和读取Blob类型的JDBC数据
  12. */
  13. public class BlobUtill {

  14.     public void getBlob() {//读取Blob数据
  15.         Connection con = null;
  16.         PreparedStatement ps = null;
  17.         ResultSet rs = null;
  18.         try {
  19.             con = JDBCTools.getConnection();
  20.             String sql = "SELECT id,name,age,picture FROM animal WHERE id=5";
  21.             ps = con.prepareStatement(sql);
  22.             rs = ps.executeQuery();
  23.             if (rs.next()) {
  24.                 int id = rs.getInt(1);
  25.                 String name = rs.getString(2);
  26.                 int age = rs.getInt(3);

  27.                 Blob picture = rs.getBlob(4);//得到Blob对象
  28.                 //开始读入文件
  29.                 InputStream in = picture.getBinaryStream();
  30.                 OutputStream out = new FileOutputStream("cat.png");
  31.                 byte[] buffer = new byte[1024];
  32.                 int len = 0;
  33.                 while ((len = in.read(buffer)) != -1) {
  34.                     out.write(buffer, 0, len);
  35.                 }
  36.             }
  37.         } catch (Exception e) {
  38.             e.printStackTrace();
  39.         }
  40.     }

  41.     public void insertBlob() {//插入Blob
  42.         Connection con = null;
  43.         PreparedStatement ps = null;
  44.         try {
  45.             con = JDBCTools.getConnection();
  46.             String sql = "INSERT INTO animal(name,age,picture) VALUES(?,?,?)";
  47.             ps = con.prepareStatement(sql);
  48.             ps.setString(1, "TheCat");
  49.             ps.setInt(2, 8);
  50.             InputStream in = new FileInputStream("J:/test1/TomCat.png");//生成被插入文件的节点流
  51.             //设置Blob
  52.             ps.setBlob(3, in);

  53.             ps.executeUpdate();
  54.         } catch (Exception e) {
  55.             e.printStackTrace();
  56.         } finally {
  57.             JDBCTools.release(con, ps);
  58.         }
  59.     }

  60. }
复制代码
  1. package org.springboot.wechatcity.utill;

  2. import java.io.InputStream;
  3. import java.sql.*;
  4. import java.util.Properties;

  5. /**
  6. * JDBC工具类  用来建立连接和释放连接
  7. */
  8. public class JDBCTools {

  9.     public static Connection getConnection() throws Exception {//连接数据库
  10.         String driverClass = "com.mysql.cj.jdbc.Driver";
  11.         String url = "jdbc:mysql://IP号:端口号/hmCity?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai";
  12.         String user = "";
  13.         String password = "";

  14.         Properties properties = new Properties();

  15.         InputStream in = Review.class.getClassLoader().getResourceAsStream("jdbc.properties");
  16.         properties.load(in);

  17.         driverClass = properties.getProperty("driver");
  18.         url = properties.getProperty("jdbcurl");
  19.         user = properties.getProperty("user");
  20.         password = properties.getProperty("password");
  21.         Class.forName(driverClass);
  22.         return DriverManager.getConnection(url, user, password);
  23.     }

  24.     public static void release(Connection con, Statement state) {//关闭数据库连接
  25.         if (state != null) {
  26.             try {
  27.                 state.close();
  28.             } catch (SQLException e) {
  29.                 e.printStackTrace();
  30.             }
  31.         }
  32.         if (con != null) {
  33.             try {
  34.                 con.close();
  35.             } catch (SQLException e) {
  36.                 e.printStackTrace();
  37.             }
  38.         }

  39.     }

  40.     public static void release(ResultSet rs, Connection con, Statement state) {//关闭数据库连接
  41.         if (rs != null) {
  42.             try {
  43.                 rs.close();
  44.             } catch (SQLException e) {
  45.                 e.printStackTrace();
  46.             }
  47.         }
  48.         if (state != null) {
  49.             try {
  50.                 state.close();
  51.             } catch (SQLException e) {
  52.                 e.printStackTrace();
  53.             }
  54.         }
  55.         if (con != null) {
  56.             try {
  57.                 con.close();
  58.             } catch (SQLException e) {
  59.                 e.printStackTrace();
  60.             }
  61.         }
  62.     }
  63. }
复制代码
Method2 详细代码示例:包括存和取的代码

示例:前端以表单形式提交数据信息和图片,后台以MultipartFile类型接收图片,并对图片进行BASE64编码,存储在mysql数据库中。
1.BASE64存图片。
note:建议图片处理部分单独写在service层,比较符合分层规则。
  1. //头部信息
  2. import org.springframework.web.multipart.MultipartFile;
  3. import sun.misc.BASE64Encoder;
  4. import java.io.IOException;
  5. import java.util.ArrayList;
  6. import java.util.List;
复制代码
  1. /**
  2.      * TODO 将用户上传的信息存入数据库中
  3.      * 图片以MultipartFile格式上传
  4.      * @return
  5.      */
  6.     @CrossOrigin(origins = {"*", "3600"})  //跨域注解,所有域名都可访问,且cookie的有效期为3600秒
  7.     @RequestMapping(value = "/pushMessageParam", method = RequestMethod.POST)
  8.     public int pushMessageBody(@RequestParam String id, MultipartFile file1, MultipartFile file2, MultipartFile file3) throws IOException{//若参数为map或json格式,必须写@RequestBody

  9.         List<MultipartFile> files =new ArrayList<>();//保存用户上传的所有图片,最多三张。
  10.         files.add(file1);
  11.         files.add(file2);
  12.         files.add(file3);

  13. //****给上传的所有jpg、jpeg格式的图片添加头部header(这样取得时候不用解码,直接拿值就行),并进行转码。****
  14.                 BASE64Encoder base64Encoder = new BASE64Encoder();//BASE64de 解码工具
  15.                        
  16.                                 try {
  17.                        
  18.                                     List<String> base64EncoderImgs = new ArrayList<>();//存放转码后的图片
  19.                                     String header = "";//为转码后的图片添加头部信息
  20.                        
  21.                                     for (int i = 0; i < files.size(); i++) {//遍历所有文件
  22.                                         if (files.get(i) != null) {
  23.                                             if (!files.get(i).getOriginalFilename().endsWith(".jpg") && !files.get(i).getOriginalFilename().endsWith(".jpeg")) {
  24.                                                 System.out.println("文件格式非法!");
  25.                                             } else if ("jpg".equals(files.get(i).getOriginalFilename())) {//files.get(i).getOriginalFilename() 获取文件的扩展名.jpg .jpeg
  26.                                                 header = "data:image/jpg;base64,";
  27.                                             } else if ("jpeg".equals(files.get(i).getOriginalFilename())) {
  28.                                                 header = "data:image/jpeg;base64,";
  29.                                             }
  30.                                             base64EncoderImgs.add(header + base64Encoder.encode(files.get(i).getBytes()));//转码
  31.                                         } else {
  32.                                             base64EncoderImgs.add(null);
  33.                                         }
  34.                                     }
  35.                                         } catch (IOException e) {
  36.                                     e.printStackTrace();
  37.                                 }


  38.         subMessageService.saveSubMessage(new SubMessage(id, base64EncoderImgs.get(0),
  39.                 base64EncoderImgs.get(1), base64EncoderImgs.get(2));
  40.         System.out.println("用户消息已存入数据库!");

  41.         return 0;
  42.     }
复制代码
2.BASE64取图片及前端显示测试
  1.     //直接取值返给前端就行
  2.     @RequestMapping(value = "/getCrowdInfoById", method = RequestMethod.GET)
  3.     public String getCrowdInfoById() {
  4.         CrowdInfo crowdInfo = new CrowdInfo();
  5.         crowdInfo.setId(3);

  6.         return crowdInfoService.getCrowdInfoById(crowdInfo).getPicBase64();//直接返回前端base64编码后的图片
  7.     }
复制代码
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <title>Title</title>
  6. </head>
  7. <!--<script src="base64.js"></script>-->
  8. <body>

  9. <img src="" width="350px" height="500px" id="kk">

  10. <!--测试base64取图片的方式-->
  11. <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
  12. <script type="text/javascript">
  13.     function getCode() {
  14.         $.ajax({
  15.             url: '/getCrowdInfoById',
  16.             type: 'get',
  17.             dataType:'text',
  18.             data: {},
  19.             success: function (result) {
  20.                 document.getElementById("kk").setAttribute("src", result);
  21.             }
  22.         })
  23.     }

  24.     window.onload = function () {
  25.         getCode();
  26.     }

  27. </script>
  28. </body>
  29. </html>
复制代码
result如下:


Method3 详细代码示例:

示例1:前端以form表单上传图片时,可以采取以下这种方法存储。
  1. @RequestMapping(value = "/upDrugImg.htm", method = RequestMethod.POST)
  2.     public ModelAndView upDrugImg(@RequestParam(value = "imgFile", required = false) MultipartFile file, HttpServletRequest request) {
  3.     //file是imgFile的别名,只能上传一张图  
  4.         String path = request.getSession().getServletContext().getRealPath("drugIMG");
  5.         String fileName = file.getOriginalFilename();
  6.         // 获取上传文件类型的扩展名,先得到.的位置,再截取从.的下一个位置到文件的最后,最后得到扩展名
  7.         String ext = fileName.substring(fileName.lastIndexOf(".") + 1,fileName.length());
  8.         // 对扩展名进行小写转换
  9.         ext = ext.toLowerCase();
  10.         // 定义一个数组,用于保存可上传的文件类型
  11.         List fileTypes = new ArrayList();
  12.         fileTypes.add("jpg");
  13.         fileTypes.add("jpeg");
  14.         fileTypes.add("bmp");
  15.         fileTypes.add("gif");
  16.         if (!fileTypes.contains(ext)) { // 如果扩展名属于允许上传的类型,则创建文件
  17.             System.out.println("文件类型不允许");
  18.             return new ModelAndView("errorpage/404");
  19.         }
  20.         // String fileName = new Date().getTime()+".jpg";
  21.         File targetFile = new File(path, fileName);
  22.         if (!targetFile.exists()) {
  23.             targetFile.mkdirs();
  24.         }
  25.         // 保存
  26.         try {
  27.         //使用此方法保存必须要绝对路径且文件夹必须已存在,否则报错
  28.             file.transferTo(targetFile);
  29.         } catch (Exception e) {
  30.             // e.printStackTrace();
  31.             return new ModelAndView("errorpage/500");
  32.         }
  33.         
  34. //******************这部分根据自己需求写******************
  35.         //将图片名存入数据库
  36.         String drugImg = "/drugIMG/" + fileName;
  37.         Drug drug = (Drug) request.getSession().getAttribute("currentDrug");
  38.         drug.setDrug_picture(drugImg);
  39.         int flag = drugService.upDrugImg(drug);
  40.         if (flag != 1) {
  41.             // System.out.println("info:upload image failed!");
  42.             return new ModelAndView("redirect:./goUpDrugImg.htm");
  43.         }
  44.         return new ModelAndView("redirect:./goAllDrugByHouse.htm", "updown", "down");
  45.     }
复制代码
前端jsp页面及后台实体类。

示例2:小程序前端以upload()方式上传图片,后台接收将图片存储到服务器,并随机生成不重复的图片名,最后将图片名存入mysql数据库。
1.SpringContextUtil工具类,直接copy就行
  1. package org.springboot.wechatcity.utill;

  2. import org.springframework.beans.BeansException;
  3. import org.springframework.context.ApplicationContext;
  4. import org.springframework.context.ApplicationContextAware;
  5. import org.springframework.stereotype.Component;

  6. /**
  7. * Spring工具类
  8. * 在非spring生命周期的地方使用javabean
  9. * @author _Yuan
  10. */
  11. @SuppressWarnings("unchecked")
  12. @Component
  13. public class SpringContextUtil implements ApplicationContextAware {
  14.     private static ApplicationContext appContext;

  15.     @Override
  16.     public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
  17.         appContext = applicationContext;
  18.     }

  19.     public static ApplicationContext getApplicationContext() {
  20.         return appContext;
  21.     }

  22.     //通过name,以及Clazz返回指定的Bean
  23.     public static <T> T getBean(String name, Class<T> clazz) throws BeansException {
  24.         return (T) appContext.getBean(name);
  25.     }

  26.     //通过name获取 Bean.
  27.     public static Object getBean(String name){
  28.         return getApplicationContext().getBean(name);
  29.     }

  30.     //通过class获取Bean.
  31.     public static <T> T getBean(Class<T> clazz){
  32.         return getApplicationContext().getBean(clazz);
  33.     }

  34. }
复制代码
2.上传图片类
  1. import org.apache.commons.fileupload.FileItem;
  2. import org.apache.commons.fileupload.disk.DiskFileItemFactory;
  3. import org.apache.commons.fileupload.servlet.ServletFileUpload;
  4. import org.slf4j.Logger;
  5. import org.slf4j.LoggerFactory;
  6. import org.springframework.web.bind.annotation.CrossOrigin;
  7. import javax.annotation.Resource;
  8. import javax.servlet.ServletException;
  9. import javax.servlet.annotation.WebServlet;
  10. import javax.servlet.http.HttpServletRequest;
  11. import javax.servlet.http.HttpServletResponse;
  12. import java.io.*;
  13. import java.sql.ResultSet;
  14. import java.sql.SQLException;
  15. import java.util.*;
  16. import java.io.File;
  17. import javax.servlet.http.HttpServlet;


  18. /**
  19. * 图片上传到服务器,并将图片名存入数据库
  20. *
  21. * @author _Yuan
  22. * @since 2020年6月10日00:14:45
  23. */

  24. @CrossOrigin(origins = {"*", "3600"})  //跨域注解,所有域名都可访问,且cookie的有效期为3600秒
  25. @WebServlet(name = "firstServlet", urlPatterns = "/uploadPicture")  //标记为servlet,以便启动器扫描。
  26. public class UploadPictureController extends HttpServlet {

  27.     private static final Logger logger = LoggerFactory.getLogger(UploadPictureController.class);//日志
  28.    
  29.     @Override
  30.     public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

  31.         Map<String, Object> resultMap = new HashMap<>();//存返回信息,建议写,较规范

  32.         //获取文件需要上传到的路径
  33.         @SuppressWarnings("deprecation")
  34.         String path = request.getRealPath("/upload") + "/";

  35.         // 判断存放上传文件的目录是否存在(不存在则创建)
  36.         File dir = new File(path);
  37.         if (!dir.exists()) {
  38.             dir.mkdir();
  39.         }
  40.         logger.debug("path=" + path);

  41.         try {
  42.             //使用Apache文件上传组件处理文件上传步骤:
  43.             //1、创建一个DiskFileItemFactory工厂
  44.             DiskFileItemFactory factory = new DiskFileItemFactory();
  45.             //2、创建一个文件上传解析器
  46.             ServletFileUpload upload = new ServletFileUpload(factory);
  47.             //3、使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List<FileItem>集合,每一个FileItem对应一个Form表单的输入项
  48.             List<FileItem> list = upload.parseRequest(request);

  49. //****看需求,我是一次只能传一张图,其实可以不用写成List***
  50.             List<String> names = new ArrayList<>();//用于存放所有图片名

  51.             for (FileItem item : list) {
  52.                 //如果fileitem中封装的是普通输入项的数据
  53.                 if (item.isFormField()) {
  54.                     String name = item.getFieldName();
  55.                     //解决普通输入项的数据的中文乱码问题
  56.                     String value = item.getString("UTF-8");
  57.                     System.out.println(name + "=" + value);
  58.                 } else {//如果fileitem中封装的是上传文件
  59.                     //得到上传的文件名称,
  60.                     String uuid = UUID.randomUUID().toString().replace("-", "");//UUID生成不重复的一串数字
  61.                     String filename = uuid + "." + "jpg";
  62.                     names.add(filename);
  63.                     System.out.println("文件名:" + filename);

  64.                     //获取item中的上传文件的输入流
  65.                     InputStream in = item.getInputStream();
  66.                     //创建一个文件输出流
  67.                     FileOutputStream out = new FileOutputStream(path + "\" + filename);
  68.                     //创建一个缓冲区
  69.                     byte buffer[] = new byte[1024];
  70.                     //判断输入流中的数据是否已经读完的标识
  71.                     int len = 0;
  72.                     //循环将输入流读入到缓冲区当中,(len=in.read(buffer))>0就表示in里面还有数据
  73.                     while ((len = in.read(buffer)) > 0) {
  74.                         //使用FileOutputStream输出流将缓冲区的数据写入到指定的目录(savePath + "\" + filename)当中
  75.                         out.write(buffer, 0, len);
  76.                     }
  77.                     //关闭输入流
  78.                     in.close();
  79.                     //关闭输出流
  80.                     out.close();
  81.                     //删除处理文件上传时生成的临时文件
  82.                     item.delete();
  83.                     System.out.println("文件上传服务器成功!");
  84.                 }
  85.             }
  86.             
  87.             
  88.             //上传所有文件名
  89.             System.out.println("图片名正在上传...请稍等");
  90.             //******非spring生命周期用注解需要用到SpringContextUtil工具类*****
  91.             SubMessageService subMessageService = SpringContextUtil.getBean("sub", SubMessageService.class);

  92.             GetInfoId id = new GetInfoId();//为了获取ID,专门写的类
  93.             int ID = id.getID();
  94.             if (names.size() != 0) {//上传了图片
  95.                 try {
  96.                     subMessageService.uploadAllPictureNames(new PicturesNames(ID, names.get(0), null, null));//根据Id更新所有图片
  97.                     System.out.println("消息ID为:" + ID);
  98.                     System.out.println("图片名已上传数据库成功~");
  99.                 }catch (Exception e){
  100.                     e.printStackTrace();
  101.                 }
  102.             } else {
  103.                 System.out.println("未上传图片");
  104.             }

  105.         } catch (Exception e) {
  106.             System.out.println("文件上传失败!");
  107.             e.printStackTrace();

  108.         }


  109.         resultMap.put("code", 0);
  110.         resultMap.put("msg", "图片上传成功");
  111.         return resultMap;
  112.     }
复制代码
结果:


以上就是关于MySQL存取图片的三种方式(含源码示例)的详细内容,更多关于MySQL存取图片的资料请关注脚本之家其它相关文章!

来源:https://www.jb51.net/database/319112kvn.htm
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具