關于MySQL存取圖片的三種方式(含源碼示例)
Method1:采用BLOB數據格式存圖片。
其實這種方式很不合理,數據庫大小會激增會導致簡單的查詢都及其緩慢。
Method2:采用文本格式存儲圖片。
雖然也不怎么合理,因為關系型數據庫本身就不太適合存巨長的大數據量的東西。
但是由于只涉及到base64加密和解碼,且可以都寫入后臺部分,減輕前端負擔。
Method3:將圖片單獨存放在某個服務器上,數據庫只存放他們的url地址。
最高效也是最常用的方法。
后面有展示兩種示例。
詳細代碼示例
Method1詳細代碼示例:
由于目前做的這個項目,同學A之前一直使用的這種方式將文件中的圖片讀取到數據庫表,所以我只寫了對BloB類型圖片的取數據部分的代碼。且過程較繁瑣,可用性不強,就不貼了。
這個代碼是A給我發(fā)的,實在太久了,她也忘了出處了。有人知道請艾特我一下,我標上鏈接。
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");//生成被插入文件的節(jié)點流 //設置Blob ps.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層,比較符合分層規(guī)則。
//頭部信息 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格式,必須寫@RequestBody List<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 .jpeg header = "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表單上傳圖片時,可以采取以下這種方法存儲。
@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)) { // 如果擴展名屬于允許上傳的類型,則創(chuàng)建文件 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; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { appContext = applicationContext; } public static ApplicationContext getApplicationContext() { return appContext; } //通過name,以及Clazz返回指定的Bean public 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);//日志 @Override public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Map<String, Object> resultMap = new HashMap<>();//存返回信息,建議寫,較規(guī)范 //獲取文件需要上傳到的路徑 @SuppressWarnings("deprecation") String path = request.getRealPath("/upload") + "/"; // 判斷存放上傳文件的目錄是否存在(不存在則創(chuàng)建) File dir = new File(path); if (!dir.exists()) { dir.mkdir(); } logger.debug("path=" + path); try { //使用Apache文件上傳組件處理文件上傳步驟: //1、創(chuàng)建一個DiskFileItemFactory工廠 DiskFileItemFactory factory = new DiskFileItemFactory(); //2、創(chuàng)建一個文件上傳解析器 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(); //創(chuàng)建一個文件輸出流 FileOutputStream out = new FileOutputStream(path + "\\" + filename); //創(chuàng)建一個緩沖區(qū) byte buffer[] = new byte[1024]; //判斷輸入流中的數據是否已經讀完的標識 int len = 0; //循環(huán)將輸入流讀入到緩沖區(qū)當中,(len=in.read(buffer))>0就表示in里面還有數據 while ((len = in.read(buffer)) > 0) { //使用FileOutputStream輸出流將緩沖區(qū)的數據寫入到指定的目錄(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存取圖片的資料請關注腳本之家其它相關文章!
相關文章
MySql用DATE_FORMAT截取DateTime字段的日期值
MySql截取DateTime字段的日期值可以使用DATE_FORMAT來格式化,使用方法如下2014-08-08MySQL中使用group by 是總是出現1055的錯誤(推薦)
這篇文章主要介紹了MySQL中使用group by 是總是出現1055的錯誤,小編通過查閱相關資料才把問題解決,今天小編記錄下分享到腳本之家平臺,需要的朋友可以參考下2020-02-02mysql "too many connections" 錯誤 之 mysql解決方法
解決方法是修改/etc/mysql/my.cnf,添加以下一行2009-06-06