關(guān)于MySQL存取圖片的三種方式(含源碼示例)
Method1:采用BLOB數(shù)據(jù)格式存圖片。
其實(shí)這種方式很不合理,數(shù)據(jù)庫(kù)大小會(huì)激增會(huì)導(dǎo)致簡(jiǎn)單的查詢都及其緩慢。
Method2:采用文本格式存儲(chǔ)圖片。
雖然也不怎么合理,因?yàn)殛P(guān)系型數(shù)據(jù)庫(kù)本身就不太適合存巨長(zhǎng)的大數(shù)據(jù)量的東西。
但是由于只涉及到base64加密和解碼,且可以都寫入后臺(tái)部分,減輕前端負(fù)擔(dān)。
Method3:將圖片單獨(dú)存放在某個(gè)服務(wù)器上,數(shù)據(jù)庫(kù)只存放他們的url地址。
最高效也是最常用的方法。
后面有展示兩種示例。
詳細(xì)代碼示例
Method1詳細(xì)代碼示例:
由于目前做的這個(gè)項(xiàng)目,同學(xué)A之前一直使用的這種方式將文件中的圖片讀取到數(shù)據(jù)庫(kù)表,所以我只寫了對(duì)BloB類型圖片的取數(shù)據(jù)部分的代碼。且過程較繁瑣,可用性不強(qiáng),就不貼了。
這個(gè)代碼是A給我發(fā)的,實(shí)在太久了,她也忘了出處了。有人知道請(qǐng)艾特我一下,我標(biāo)上鏈接。
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數(shù)據(jù) */ public class BlobUtill { public void getBlob() {//讀取Blob數(shù)據(jù) 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對(duì)象 //開始讀入文件 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é)點(diǎn)流 //設(shè)置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 {//連接數(shù)據(jù)庫(kù) String driverClass = "com.mysql.cj.jdbc.Driver"; String url = "jdbc:mysql://IP號(hào):端口號(hào)/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) {//關(guān)閉數(shù)據(jù)庫(kù)連接 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) {//關(guān)閉數(shù)據(jù)庫(kù)連接 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 詳細(xì)代碼示例:包括存和取的代碼
示例:前端以表單形式提交數(shù)據(jù)信息和圖片,后臺(tái)以MultipartFile類型接收?qǐng)D片,并對(duì)圖片進(jìn)行BASE64編碼,存儲(chǔ)在mysql數(shù)據(jù)庫(kù)中。
1.BASE64存圖片。
note:建議圖片處理部分單獨(dú)寫在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 將用戶上傳的信息存入數(shù)據(jù)庫(kù)中 * 圖片以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{//若參數(shù)為map或json格式,必須寫@RequestBody List<MultipartFile> files =new ArrayList<>();//保存用戶上傳的所有圖片,最多三張。 files.add(file1); files.add(file2); files.add(file3); //****給上傳的所有jpg、jpeg格式的圖片添加頭部header(這樣取得時(shí)候不用解碼,直接拿值就行),并進(jìn)行轉(zhuǎn)碼。**** BASE64Encoder base64Encoder = new BASE64Encoder();//BASE64de 解碼工具 try { List<String> base64EncoderImgs = new ArrayList<>();//存放轉(zhuǎn)碼后的圖片 String header = "";//為轉(zhuǎn)碼后的圖片添加頭部信息 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() 獲取文件的擴(kuò)展名.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()));//轉(zhuǎn)碼 } 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("用戶消息已存入數(shù)據(jù)庫(kù)!"); return 0; }
2.BASE64取圖片及前端顯示測(cè)試
//直接取值返給前端就行 @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"> <!--測(cè)試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 詳細(xì)代碼示例:
示例1:前端以form表單上傳圖片時(shí),可以采取以下這種方法存儲(chǔ)。
@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(); // 獲取上傳文件類型的擴(kuò)展名,先得到.的位置,再截取從.的下一個(gè)位置到文件的最后,最后得到擴(kuò)展名 String ext = fileName.substring(fileName.lastIndexOf(".") + 1,fileName.length()); // 對(duì)擴(kuò)展名進(jìn)行小寫轉(zhuǎn)換 ext = ext.toLowerCase(); // 定義一個(gè)數(shù)組,用于保存可上傳的文件類型 List fileTypes = new ArrayList(); fileTypes.add("jpg"); fileTypes.add("jpeg"); fileTypes.add("bmp"); fileTypes.add("gif"); if (!fileTypes.contains(ext)) { // 如果擴(kuò)展名屬于允許上傳的類型,則創(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 { //使用此方法保存必須要絕對(duì)路徑且文件夾必須已存在,否則報(bào)錯(cuò) file.transferTo(targetFile); } catch (Exception e) { // e.printStackTrace(); return new ModelAndView("errorpage/500"); } //******************這部分根據(jù)自己需求寫****************** //將圖片名存入數(shù)據(jù)庫(kù) 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頁(yè)面及后臺(tái)實(shí)體類。
示例2:小程序前端以u(píng)pload()方式上傳圖片,后臺(tái)接收將圖片存儲(chǔ)到服務(wù)器,并隨機(jī)生成不重復(fù)的圖片名,最后將圖片名存入mysql數(shù)據(jù)庫(kù)。
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; /** * 圖片上傳到服務(wù)器,并將圖片名存入數(shù)據(jù)庫(kù) * * @author _Yuan * @since 2020年6月10日00:14:45 */ @CrossOrigin(origins = {"*", "3600"}) //跨域注解,所有域名都可訪問,且cookie的有效期為3600秒 @WebServlet(name = "firstServlet", urlPatterns = "/uploadPicture") //標(biāo)記為servlet,以便啟動(dòng)器掃描。 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)建一個(gè)DiskFileItemFactory工廠 DiskFileItemFactory factory = new DiskFileItemFactory(); //2、創(chuàng)建一個(gè)文件上傳解析器 ServletFileUpload upload = new ServletFileUpload(factory); //3、使用ServletFileUpload解析器解析上傳數(shù)據(jù),解析結(jié)果返回的是一個(gè)List<FileItem>集合,每一個(gè)FileItem對(duì)應(yīng)一個(gè)Form表單的輸入項(xiàng) List<FileItem> list = upload.parseRequest(request); //****看需求,我是一次只能傳一張圖,其實(shí)可以不用寫成List*** List<String> names = new ArrayList<>();//用于存放所有圖片名 for (FileItem item : list) { //如果fileitem中封裝的是普通輸入項(xiàng)的數(shù)據(jù) if (item.isFormField()) { String name = item.getFieldName(); //解決普通輸入項(xiàng)的數(shù)據(jù)的中文亂碼問題 String value = item.getString("UTF-8"); System.out.println(name + "=" + value); } else {//如果fileitem中封裝的是上傳文件 //得到上傳的文件名稱, String uuid = UUID.randomUUID().toString().replace("-", "");//UUID生成不重復(fù)的一串?dāng)?shù)字 String filename = uuid + "." + "jpg"; names.add(filename); System.out.println("文件名:" + filename); //獲取item中的上傳文件的輸入流 InputStream in = item.getInputStream(); //創(chuàng)建一個(gè)文件輸出流 FileOutputStream out = new FileOutputStream(path + "\\" + filename); //創(chuàng)建一個(gè)緩沖區(qū) byte buffer[] = new byte[1024]; //判斷輸入流中的數(shù)據(jù)是否已經(jīng)讀完的標(biāo)識(shí) int len = 0; //循環(huán)將輸入流讀入到緩沖區(qū)當(dāng)中,(len=in.read(buffer))>0就表示in里面還有數(shù)據(jù) while ((len = in.read(buffer)) > 0) { //使用FileOutputStream輸出流將緩沖區(qū)的數(shù)據(jù)寫入到指定的目錄(savePath + "\\" + filename)當(dāng)中 out.write(buffer, 0, len); } //關(guān)閉輸入流 in.close(); //關(guān)閉輸出流 out.close(); //刪除處理文件上傳時(shí)生成的臨時(shí)文件 item.delete(); System.out.println("文件上傳服務(wù)器成功!"); } } //上傳所有文件名 System.out.println("圖片名正在上傳...請(qǐng)稍等"); //******非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));//根據(jù)Id更新所有圖片 System.out.println("消息ID為:" + ID); System.out.println("圖片名已上傳數(shù)據(jù)庫(kù)成功~"); }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; }
結(jié)果:
以上就是關(guān)于MySQL存取圖片的三種方式(含源碼示例)的詳細(xì)內(nèi)容,更多關(guān)于MySQL存取圖片的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
MySql用DATE_FORMAT截取DateTime字段的日期值
MySql截取DateTime字段的日期值可以使用DATE_FORMAT來格式化,使用方法如下2014-08-08MySQL中使用group by 是總是出現(xiàn)1055的錯(cuò)誤(推薦)
這篇文章主要介紹了MySQL中使用group by 是總是出現(xiàn)1055的錯(cuò)誤,小編通過查閱相關(guān)資料才把問題解決,今天小編記錄下分享到腳本之家平臺(tái),需要的朋友可以參考下2020-02-02MySQL對(duì)小數(shù)進(jìn)行四舍五入的操作實(shí)現(xiàn)
數(shù)學(xué)函數(shù)是MySQL中常用的一類函數(shù),其主要用于處理數(shù)字,包括整型和浮點(diǎn)數(shù)等等,本文主要介紹了MySQL對(duì)小數(shù)進(jìn)行四舍五入的操作實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2023-08-08mysql內(nèi)連接,連續(xù)兩次使用同一張表,自連接方式
這篇文章主要介紹了mysql內(nèi)連接,連續(xù)兩次使用同一張表,自連接方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12Centos6.4編譯安裝mysql 8.0.0 詳細(xì)教程
這篇文章主要為大家分享了Centos6.4編譯安裝mysql 8.0.0 詳細(xì)教程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-11-11mysql "too many connections" 錯(cuò)誤 之 mysql解決方法
解決方法是修改/etc/mysql/my.cnf,添加以下一行2009-06-06MySQL查看數(shù)據(jù)庫(kù)狀態(tài)命令詳細(xì)講解
在工作中,有時(shí)候我們需要了解MySQL服務(wù)器的狀態(tài)信息,下面這篇文章主要給大家介紹了關(guān)于MySQL查看數(shù)據(jù)庫(kù)狀態(tài)命令的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-03-03