Method1:采用BLOB数据格式存图片。
其实这种方式很不合理,数据库大小会激增会导致简单的查询都及其缓慢。
Method2:采用文本格式存储图片。
虽然也不怎么合理,因为关系型数据库本身就不太适合存巨长的大数据量的东西。
但是由于只涉及到base64加密和解码,且可以都写入后台部分,减轻前端负担。
Method3:将图片单独存放在某个服务器上,数据库只存放他们的url地址。
最高效也是最常用的方法。
后面有展示两种示例。
详细代码示例
Method1详细代码示例:
由于目前做的这个项目,同学A之前一直使用的这种方式将文件中的图片读取到数据库表,所以我只写了对BloB类型图片的取数据部分的代码。且过程较繁琐,可用性不强,就不贴了。
这个代码是A给我发的,实在太久了,她也忘了出处了。有人知道请艾特我一下,我标上链接。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | package org.springboot.wechatcity.utill; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.sql.Blob; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; /** * 存入和读取Blob类型的JDBC数据 */ public class BlobUtill { public void getBlob() { //读取Blob数据 Connection con = null ; PreparedStatement ps = null ; ResultSet rs = null ; try { con = JDBCTools.getConnection(); String sql = "SELECT id,name,age,picture FROM animal WHERE id=5" ; ps = con.prepareStatement(sql); rs = ps.executeQuery(); if (rs.next()) { int id = rs.getInt( 1 ); String name = rs.getString( 2 ); int age = rs.getInt( 3 ); Blob picture = rs.getBlob( 4 ); //得到Blob对象 //开始读入文件 InputStream in = picture.getBinaryStream(); OutputStream out = new FileOutputStream( "cat.png" ); byte [] buffer = new byte [ 1024 ]; int len = 0 ; while ((len = in.read(buffer)) != - 1 ) { out.write(buffer, 0 , len); } } } catch (Exception e) { e.printStackTrace(); } } public void insertBlob() { //插入Blob Connection con = null ; PreparedStatement ps = null ; try { con = JDBCTools.getConnection(); String sql = "INSERT INTO animal(name,age,picture) VALUES(?,?,?)" ; ps = con.prepareStatement(sql); ps.setString( 1 , "TheCat" ); ps.setInt( 2 , 8 ); InputStream in = new FileInputStream( "J:/test1/TomCat.png" ); //生成被插入文件的节点流 //设置Blob ps.setBlob( 3 , in); ps.executeUpdate(); } catch (Exception e) { e.printStackTrace(); } finally { JDBCTools.release(con, ps); } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | package org.springboot.wechatcity.utill; import java.io.InputStream; import java.sql.*; import java.util.Properties; /** * JDBC工具类 用来建立连接和释放连接 */ public class JDBCTools { public static Connection getConnection() throws Exception { //连接数据库 String driverClass = "com.mysql.cj.jdbc.Driver" ; String url = "jdbc:mysql://IP号:端口号/hmCity?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai" ; String user = "" ; String password = "" ; Properties properties = new Properties(); InputStream in = Review. class .getClassLoader().getResourceAsStream( "jdbc.properties" ); properties.load(in); driverClass = properties.getProperty( "driver" ); url = properties.getProperty( "jdbcurl" ); user = properties.getProperty( "user" ); password = properties.getProperty( "password" ); Class.forName(driverClass); return DriverManager.getConnection(url, user, password); } public static void release(Connection con, Statement state) { //关闭数据库连接 if (state != null ) { try { state.close(); } catch (SQLException e) { e.printStackTrace(); } } if (con != null ) { try { con.close(); } catch (SQLException e) { e.printStackTrace(); } } } public static void release(ResultSet rs, Connection con, Statement state) { //关闭数据库连接 if (rs != null ) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if (state != null ) { try { state.close(); } catch (SQLException e) { e.printStackTrace(); } } if (con != null ) { try { con.close(); } catch (SQLException e) { e.printStackTrace(); } } } } |
Method2 详细代码示例:包括存和取的代码
示例:前端以表单形式提交数据信息和图片,后台以MultipartFile类型接收图片,并对图片进行BASE64编码,存储在mysql数据库中。
1.BASE64存图片。
note:建议图片处理部分单独写在service层,比较符合分层规则。
1 2 3 4 5 6 | //头部信息 import org.springframework.web.multipart.MultipartFile; import sun.misc.BASE64Encoder; import java.io.IOException; import java.util.ArrayList; import java.util.List; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | /** * TODO 将用户上传的信息存入数据库中 * 图片以MultipartFile格式上传 * @return */ @CrossOrigin (origins = { "*" , "3600" }) //跨域注解,所有域名都可访问,且cookie的有效期为3600秒 @RequestMapping (value = "/pushMessageParam" , method = RequestMethod.POST) public int pushMessageBody( @RequestParam String id, MultipartFile file1, MultipartFile file2, MultipartFile file3) throws IOException{ //若参数为map或json格式,必须写@RequestBody List files = new ArrayList(); //保存用户上传的所有图片,最多三张。 files.add(file1); files.add(file2); files.add(file3); //****给上传的所有jpg、jpeg格式的图片添加头部header(这样取得时候不用解码,直接拿值就行),并进行转码。**** BASE64Encoder base64Encoder = new BASE64Encoder(); //BASE64de 解码工具 try { List base64EncoderImgs = new ArrayList(); //存放转码后的图片 String header = "" ; //为转码后的图片添加头部信息 for ( int i = 0 ; i |
2.BASE64取图片及前端显示测试
1 2 3 4 5 6 7 8 | //直接取值返给前端就行 @RequestMapping (value = "/getCrowdInfoById" , method = RequestMethod.GET) public String getCrowdInfoById() { CrowdInfo crowdInfo = new CrowdInfo(); crowdInfo.setId( 3 ); return crowdInfoService.getCrowdInfoById(crowdInfo).getPicBase64(); //直接返回前端base64编码后的图片 } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | < title >Title</ title >< img decoding = "async" src = "" width = "350px" height = "500px" id = "kk" > function getCode() { $.ajax({ url: '/getCrowdInfoById', type: 'get', dataType:'text', data: {}, success: function (result) { document.getElementById("kk").setAttribute("src", result); } }) } window.onload = function () { getCode(); } |
result如下:
Method3 详细代码示例:
示例1:前端以form表单上传图片时,可以采取以下这种方法存储。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | @RequestMapping (value = "/upDrugImg.htm" , method = RequestMethod.POST) public ModelAndView upDrugImg( @RequestParam (value = "imgFile" , required = false ) MultipartFile file, HttpServletRequest request) { //file是imgFile的别名,只能上传一张图 String path = request.getSession().getServletContext().getRealPath( "drugIMG" ); String fileName = file.getOriginalFilename(); // 获取上传文件类型的扩展名,先得到.的位置,再截取从.的下一个位置到文件的最后,最后得到扩展名 String ext = fileName.substring(fileName.lastIndexOf( "." ) + 1 ,fileName.length()); // 对扩展名进行小写转换 ext = ext.toLowerCase(); // 定义一个数组,用于保存可上传的文件类型 List fileTypes = new ArrayList(); fileTypes.add( "jpg" ); fileTypes.add( "jpeg" ); fileTypes.add( "bmp" ); fileTypes.add( "gif" ); if (!fileTypes.contains(ext)) { // 如果扩展名属于允许上传的类型,则创建文件 System.out.println( "文件类型不允许" ); return new ModelAndView( "errorpage/404" ); } // String fileName = new Date().getTime()+".jpg"; File targetFile = new File(path, fileName); if (!targetFile.exists()) { targetFile.mkdirs(); } // 保存 try { //使用此方法保存必须要绝对路径且文件夹必须已存在,否则报错 file.transferTo(targetFile); } catch (Exception e) { // e.printStackTrace(); return new ModelAndView( "errorpage/500" ); } //******************这部分根据自己需求写****************** //将图片名存入数据库 String drugImg = "/drugIMG/" + fileName; Drug drug = (Drug) request.getSession().getAttribute( "currentDrug" ); drug.setDrug_picture(drugImg); int flag = drugService.upDrugImg(drug); if (flag != 1 ) { // System.out.println("info:upload image failed!"); return new ModelAndView( "redirect:./goUpDrugImg.htm" ); } return new ModelAndView( "redirect:./goAllDrugByHouse.htm" , "updown" , "down" ); } |
前端jsp页面及后台实体类。
示例2:小程序前端以upload()方式上传图片,后台接收将图片存储到服务器,并随机生成不重复的图片名,最后将图片名存入mysql数据库。
1.SpringContextUtil工具类,直接copy就行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | package org.springboot.wechatcity.utill; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component; /** * Spring工具类 * 在非spring生命周期的地方使用javabean * @author _Yuan */ @SuppressWarnings ( "unchecked" ) @Component public class SpringContextUtil implements ApplicationContextAware { private static ApplicationContext appContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { appContext = applicationContext; } public static ApplicationContext getApplicationContext() { return appContext; } //通过name,以及Clazz返回指定的Bean public static T getBean(String name, Class clazz) throws BeansException { return (T) appContext.getBean(name); } //通过name获取 Bean. public static Object getBean(String name){ return getApplicationContext().getBean(name); } //通过class获取Bean. public static T getBean(Class clazz){ return getApplicationContext().getBean(clazz); } } |
2.上传图片类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.CrossOrigin; import javax.annotation.Resource; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.*; import java.sql.ResultSet; import java.sql.SQLException; import java.util.*; import java.io.File; import javax.servlet.http.HttpServlet; /** * 图片上传到服务器,并将图片名存入数据库 * * @author _Yuan * @since 2020年6月10日00:14:45 */ @CrossOrigin (origins = { "*" , "3600" }) //跨域注解,所有域名都可访问,且cookie的有效期为3600秒 @WebServlet (name = "firstServlet" , urlPatterns = "/uploadPicture" ) //标记为servlet,以便启动器扫描。 public class UploadPictureController extends HttpServlet { private static final Logger logger = LoggerFactory.getLogger(UploadPictureController. class ); //日志 @Override public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Map resultMap = new HashMap(); //存返回信息,建议写,较规范 //获取文件需要上传到的路径 @SuppressWarnings ( "deprecation" ) String path = request.getRealPath( "/upload" ) + "/" ; // 判断存放上传文件的目录是否存在(不存在则创建) File dir = new File(path); if (!dir.exists()) { dir.mkdir(); } logger.debug( "path=" + path); try { //使用Apache文件上传组件处理文件上传步骤: //1、创建一个DiskFileItemFactory工厂 DiskFileItemFactory factory = new DiskFileItemFactory(); //2、创建一个文件上传解析器 ServletFileUpload upload = new ServletFileUpload(factory); //3、使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List集合,每一个FileItem对应一个Form表单的输入项 List list = upload.parseRequest(request); //****看需求,我是一次只能传一张图,其实可以不用写成List*** List names = new ArrayList(); //用于存放所有图片名 for (FileItem item : list) { //如果fileitem中封装的是普通输入项的数据 if (item.isFormField()) { String name = item.getFieldName(); //解决普通输入项的数据的中文乱码问题 String value = item.getString( "UTF-8" ); System.out.println(name + "=" + value); } else { //如果fileitem中封装的是上传文件 //得到上传的文件名称, String uuid = UUID.randomUUID().toString().replace( "-" , "" ); //UUID生成不重复的一串数字 String filename = uuid + "." + "jpg" ; names.add(filename); System.out.println( "文件名:" + filename); //获取item中的上传文件的输入流 InputStream in = item.getInputStream(); //创建一个文件输出流 FileOutputStream out = new FileOutputStream(path + "\" + filename); //创建一个缓冲区 byte buffer[] = new byte [ 1024 ]; //判断输入流中的数据是否已经读完的标识 int len = 0 ; //循环将输入流读入到缓冲区当中,(len=in.read(buffer))>0就表示in里面还有数据 while ((len = in.read(buffer)) > 0 ) { //使用FileOutputStream输出流将缓冲区的数据写入到指定的目录(savePath + "\" + filename)当中 out.write(buffer, 0 , len); } //关闭输入流 in.close(); //关闭输出流 out.close(); //删除处理文件上传时生成的临时文件 item.delete(); System.out.println( "文件上传服务器成功!" ); } } //上传所有文件名 System.out.println( "图片名正在上传...请稍等" ); //******非spring生命周期用注解需要用到SpringContextUtil工具类***** SubMessageService subMessageService = SpringContextUtil.getBean( "sub" , SubMessageService. class ); GetInfoId id = new GetInfoId(); //为了获取ID,专门写的类 int ID = id.getID(); if (names.size() != 0 ) { //上传了图片 try { subMessageService.uploadAllPictureNames( new PicturesNames(ID, names.get( 0 ), null , null )); //根据Id更新所有图片 System.out.println( "消息ID为:" + ID); System.out.println( "图片名已上传数据库成功~" ); } catch (Exception e){ e.printStackTrace(); } } else { System.out.println( "未上传图片" ); } } catch (Exception e) { System.out.println( "文件上传失败!" ); e.printStackTrace(); } resultMap.put( "code" , 0 ); resultMap.put( "msg" , "图片上传成功" ); return resultMap; } |
结果:
以上就是关于MySQL存取图片的三种方式(含源码示例)的详细内容,更多关于MySQL存取图片的资料请关注IT俱乐部其它相关文章!