最近在做小程序的后台,要求将小程序用户以upload方法上传的图片保存到mysql数据库中。
然后机缘巧合三种方式都试了,所以专门整理出来分享给大家。可能有的地方说的不太对,欢迎大家帮纠正。

================================================================================

Method1:采用BLOB数据格式存图片。

其实这种方式很不合理,数据库大小会激增会导致简单的查询都及其缓慢。

Method2:采用文本格式存储图片。

虽然也不怎么合理,因为关系型数据库本身就不太适合存巨长的大数据量的东西。
但是由于只涉及到base64加密和解码,且可以都写入后台部分,减轻前端负担。

Method3:将图片单独存放在某个服务器上,数据库只存放他们的url地址。

最高效也是最常用的方法。
后面有展示两种示例。

================================================================================

详细代码示例

================================================================================

Method1详细代码示例:

由于目前做的这个项目,同学A之前一直使用的这种方式将文件中的图片读取到数据库表,所以我只写了对BloB类型图片的取数据部分的代码。且过程较繁琐,可用性不强,就不贴了。

这个代码是A给我发的,实在太久了,她也忘了出处了。有人知道请艾特我一下,我标上链接。

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() {//插入BlobConnection 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");//生成被插入文件的节点流//设置Blobps.setBlob(3, in);ps.executeUpdate();} catch (Exception e) {e.printStackTrace();} finally {JDBCTools.release(con, ps);}}}
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层,比较符合分层规则。

//头部信息
import org.springframework.web.multipart.MultipartFile;
import sun.misc.BASE64Encoder;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
 /*** 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格式,必须写@RequestBodyList<MultipartFile> files =new ArrayList<>();//保存用户上传的所有图片,最多三张。files.add(file1);files.add(file2);files.add(file3);//****给上传的所有jpg、jpeg格式的图片添加头部header(这样取得时候不用解码,直接拿值就行),并进行转码。****BASE64Encoder base64Encoder = new BASE64Encoder();//BASE64de 解码工具try {List<String> base64EncoderImgs = new ArrayList<>();//存放转码后的图片String header = "";//为转码后的图片添加头部信息for (int i = 0; i < files.size(); i++) {//遍历所有文件if (files.get(i) != null) {if (!files.get(i).getOriginalFilename().endsWith(".jpg") && !files.get(i).getOriginalFilename().endsWith(".jpeg")) {System.out.println("文件格式非法!");} else if ("jpg".equals(files.get(i).getOriginalFilename())) {//files.get(i).getOriginalFilename() 获取文件的扩展名.jpg .jpegheader = "data:image/jpg;base64,";} else if ("jpeg".equals(files.get(i).getOriginalFilename())) {header = "data:image/jpeg;base64,";}base64EncoderImgs.add(header + base64Encoder.encode(files.get(i).getBytes()));//转码} else {base64EncoderImgs.add(null);}}} catch (IOException e) {e.printStackTrace();}subMessageService.saveSubMessage(new SubMessage(id, base64EncoderImgs.get(0),base64EncoderImgs.get(1), base64EncoderImgs.get(2));System.out.println("用户消息已存入数据库!");return 0;}

2.BASE64取图片及前端显示测试

    //直接取值返给前端就行@RequestMapping(value = "/getCrowdInfoById", method = RequestMethod.GET)public String getCrowdInfoById() {CrowdInfo crowdInfo = new CrowdInfo();crowdInfo.setId(3);return crowdInfoService.getCrowdInfoById(crowdInfo).getPicBase64();//直接返回前端base64编码后的图片}
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<!--<script src="base64.js"></script>-->
<body><img src="" width="350px" height="500px" id="kk"><!--测试base64取图片的方式-->
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script type="text/javascript">function getCode() {$.ajax({url: '/getCrowdInfoById',type: 'get',dataType:'text',data: {},success: function (result) {document.getElementById("kk").setAttribute("src", result);}})}window.onload = function () {getCode();}</script>
</body>
</html>

result如下:

================================================================================

Method3 详细代码示例:

示例1:前端以form表单上传图片时,可以采取以下这种方法存储。

本代码由博友“园园的铁粉QAQ”提供,在此感谢这位朋友的无私奉献。

@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就行

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;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {appContext = applicationContext;}public static ApplicationContext getApplicationContext() {return appContext;}//通过name,以及Clazz返回指定的Beanpublic static <T> T getBean(String name, Class<T> 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> T getBean(Class<T> clazz){return getApplicationContext().getBean(clazz);}}

2.上传图片类

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);//日志@Overridepublic void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {Map<String, Object> 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>集合,每一个FileItem对应一个Form表单的输入项List<FileItem> list = upload.parseRequest(request);//****看需求,我是一次只能传一张图,其实可以不用写成List***List<String> 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存取图片的三种方式(含源码示例)相关推荐

  1. python的命名空间_python中命名空间的三种方式介绍(附示例)

    本篇文章给大家带来的内容是关于python中命名空间的三种方式介绍(附示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. python中的命名空间分三种: 内置的命名空间,在启动解 ...

  2. Nginx/Openresty日志时间显示到毫秒级的三种方法(不改源码)

    Nginx/Openresty日志时间显示到毫秒级的三种方法(不改源码) 方法一 :set (只能在server节点内) 方法二: set_by_lua (只能在server节点内) 方法三: map ...

  3. 给Teams消息附加图片的三种方式

    Teams消息支持三种不同的方式来添加图片,这篇文章我们来一起看一下这三种方式. Inline图片 var imagePath = Path.Combine(Environment.CurrentDi ...

  4. ipad使用计算机的图片大全,三种方式备份 iPad 照片

    三种方式备份 iPad 照片 是一个重要的备份照片从 iPad.这是因为这些照片记录了幸福和悲伤在你的生活.为了让他们的肉体,备份是一个不错的选择.照片通常捕获大量的存储,可能会迫使你有没有足够的空间 ...

  5. MySQL删除表的三种方式

    文章目录 drop table truncate (table) delete from 三种方式的区别 用法总结 drop table drop 是直接删除表信息,速度最快,但是无法找回数据 例如删 ...

  6. Html img显示图片的三种方式

    1.显示本地图片 2.显示网络上的图片,不过网络上的图片就是需要每次都去加载,可能会费流量 3.下面这种就是我们今天所要讲的第三种方式显示图片,它其实也就是根据http网络上的图片通过利用Data U ...

  7. MySQL模糊查询的三种方式

    文章目录 一.Mybatis常用模糊查询方法 1.使用concat("%",#{name},"%") 2.使用'%${name}%' 3.使用"%&q ...

  8. vue路由传参的三种方式/含页面刷新参数丢失解决方案(详细)

    vue路由传参的三种方式以及页面刷新参数丢失问题 一.路由传参的三种方式 1.传参方式一:params传参 2.传参方式二:路由属性配置传参 3.传参方式三:query传参 二.三种传递方式的区别 一 ...

  9. Mysql批量更新的三种方式

    前言 批量插入由于mysql的VALUES原生支持,使用较为便利. 批量更新的写法一般有三种,在更新数量较少的情况下,前两种性能不相上下.但是在更新字段增加,更新条数较多(500以上)建议使用第三种写 ...

最新文章

  1. (转)Java并发编程:线程池的使用
  2. iphone以旧换新活动_iPhone销量靠降价,安卓终于要赢了?
  3. boost::regex
  4. php写好程序后需要嵌套,什么是PHP嵌套函数?
  5. MVC3.0中使用JQuery.DataTable插件。
  6. python3 zip命令_zip错误:无效的命令参数(无法将zip文件写入终端)
  7. Class.forName(com.mysql.jdbc.driver);
  8. 最小二乘原理求解线性回归方程
  9. 跟我学android-Notification
  10. textContent与innerText
  11. 冒险岛单机版mysql_冒险岛单机版
  12. 北理校园网省流攻略之下载篇
  13. 青少年CTF-Web-CheckMe01
  14. icloud显示账户详情不可用,苹果icloud账户详情不可用怎么办 iPhone提示当前账户详情不可用怎么回事...
  15. 你知道怎样进行芝麻动态vps速度测试吗?
  16. weblogic卸载 for linux
  17. 难道天才都容易罹患精神疾病?还是西方医学不知道风邪所犯?
  18. 大雁塔尺寸_仅用一张A4纸和计算器针对西安大雁塔高度的测量
  19. koolshare docker插件使用
  20. 如何从TI官方网站导入例程

热门文章

  1. 一般PMP证书会被认为是比较可靠的认证吗?Hr怎么看待?
  2. arcgis oracle srid,什么是 SRID?
  3. 在 Rails 中生成 PDF
  4. TI | TM4C123Gx单片机之---I2C接口笔记
  5. js string转json有斜杠_如何过滤掉json字符串里面的反斜杠
  6. 价值15000的大数据全套视频免费分享!!
  7. 创建一个 Dog 类继承 Thread ,每 2 秒叫一次(汪汪汪!!),创建一个 Cat 实现 Runnable 接口,每 3 秒求抚摸一次(主人快摸摸我!!),主函数(主线程)从 1 输出到 10
  8. Python 之谷歌瓦片地图影像批量下载
  9. 计算机拨珠游戏,幼儿园小班1-5的拨珠教案
  10. 【大数据开发运维解决方案】Solr5.1+Jcseg分词器安装部署(中英文同义词、停止词配置)