關(guān)于MySQL存取圖片的三種方式(含源碼示例)
Method1:采用BLOB數(shù)據(jù)格式存圖片。
其實這種方式很不合理,數(shù)據(jù)庫大小會激增會導(dǎo)致簡單的查詢都及其緩慢。
Method2:采用文本格式存儲圖片。
雖然也不怎么合理,因為關(guān)系型數(shù)據(jù)庫本身就不太適合存巨長的大數(shù)據(jù)量的東西。
但是由于只涉及到base64加密和解碼,且可以都寫入后臺部分,減輕前端負擔。
Method3:將圖片單獨存放在某個服務(wù)器上,數(shù)據(jù)庫只存放他們的url地址。
最高效也是最常用的方法。
后面有展示兩種示例。
詳細代碼示例
Method1詳細代碼示例:
由于目前做的這個項目,同學(xué)A之前一直使用的這種方式將文件中的圖片讀取到數(shù)據(jù)庫表,所以我只寫了對BloB類型圖片的取數(shù)據(jù)部分的代碼。且過程較繁瑣,可用性不強,就不貼了。
這個代碼是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數(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對象
//開始讀入文件
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é)點流
//設(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ù)庫
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) {//關(guān)閉數(shù)據(jù)庫連接
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ù)庫連接
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 詳細代碼示例:包括存和取的代碼
示例:前端以表單形式提交數(shù)據(jù)信息和圖片,后臺以MultipartFile類型接收圖片,并對圖片進行BASE64編碼,存儲在mysql數(shù)據(jù)庫中。
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 將用戶上傳的信息存入數(shù)據(jù)庫中
* 圖片以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(這樣取得時候不用解碼,直接拿值就行),并進行轉(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() 獲取文件的擴展名.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ù)庫!");
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());
// 對擴展名進行小寫轉(zhuǎn)換
ext = ext.toLowerCase();
// 定義一個數(shù)組,用于保存可上傳的文件類型
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");
}
//******************這部分根據(jù)自己需求寫******************
//將圖片名存入數(shù)據(jù)庫
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()方式上傳圖片,后臺接收將圖片存儲到服務(wù)器,并隨機生成不重復(fù)的圖片名,最后將圖片名存入mysql數(shù)據(jù)庫。
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ù)庫
*
* @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解析器解析上傳數(shù)據(jù),解析結(jié)果返回的是一個List<FileItem>集合,每一個FileItem對應(yīng)一個Form表單的輸入項
List<FileItem> list = upload.parseRequest(request);
//****看需求,我是一次只能傳一張圖,其實可以不用寫成List***
List<String> names = new ArrayList<>();//用于存放所有圖片名
for (FileItem item : list) {
//如果fileitem中封裝的是普通輸入項的數(shù)據(jù)
if (item.isFormField()) {
String name = item.getFieldName();
//解決普通輸入項的數(shù)據(jù)的中文亂碼問題
String value = item.getString("UTF-8");
System.out.println(name + "=" + value);
} else {//如果fileitem中封裝的是上傳文件
//得到上傳的文件名稱,
String uuid = UUID.randomUUID().toString().replace("-", "");//UUID生成不重復(fù)的一串數(shù)字
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];
//判斷輸入流中的數(shù)據(jù)是否已經(jīng)讀完的標識
int len = 0;
//循環(huán)將輸入流讀入到緩沖區(qū)當中,(len=in.read(buffer))>0就表示in里面還有數(shù)據(jù)
while ((len = in.read(buffer)) > 0) {
//使用FileOutputStream輸出流將緩沖區(qū)的數(shù)據(jù)寫入到指定的目錄(savePath + "\\" + filename)當中
out.write(buffer, 0, len);
}
//關(guān)閉輸入流
in.close();
//關(guān)閉輸出流
out.close();
//刪除處理文件上傳時生成的臨時文件
item.delete();
System.out.println("文件上傳服務(wù)器成功!");
}
}
//上傳所有文件名
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));//根據(jù)Id更新所有圖片
System.out.println("消息ID為:" + ID);
System.out.println("圖片名已上傳數(shù)據(jù)庫成功~");
}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存取圖片的三種方式(含源碼示例)的詳細內(nèi)容,更多關(guān)于MySQL存取圖片的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
MySql用DATE_FORMAT截取DateTime字段的日期值
MySql截取DateTime字段的日期值可以使用DATE_FORMAT來格式化,使用方法如下2014-08-08
MySQL中使用group by 是總是出現(xiàn)1055的錯誤(推薦)
這篇文章主要介紹了MySQL中使用group by 是總是出現(xiàn)1055的錯誤,小編通過查閱相關(guān)資料才把問題解決,今天小編記錄下分享到腳本之家平臺,需要的朋友可以參考下2020-02-02
MySQL對小數(shù)進行四舍五入的操作實現(xiàn)
數(shù)學(xué)函數(shù)是MySQL中常用的一類函數(shù),其主要用于處理數(shù)字,包括整型和浮點數(shù)等等,本文主要介紹了MySQL對小數(shù)進行四舍五入的操作實現(xiàn),具有一定的參考價值,感興趣的可以了解一下2023-08-08
mysql內(nèi)連接,連續(xù)兩次使用同一張表,自連接方式
這篇文章主要介紹了mysql內(nèi)連接,連續(xù)兩次使用同一張表,自連接方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-12-12
mysql "too many connections" 錯誤 之 mysql解決方法
解決方法是修改/etc/mysql/my.cnf,添加以下一行2009-06-06
MySQL查看數(shù)據(jù)庫狀態(tài)命令詳細講解
在工作中,有時候我們需要了解MySQL服務(wù)器的狀態(tài)信息,下面這篇文章主要給大家介紹了關(guān)于MySQL查看數(shù)據(jù)庫狀態(tài)命令的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下2023-03-03

