前作:JavaWeb servlet jsp 使用七牛云API上传图片
使用mysql保存图片七牛云路径,在上传图片的时候直接上传到七牛云
前端使用了layui,图片多组上传使用了百度的WebUploader,本来想用swfupload的,但是10年前的东西实在不太行,我连跑都跑不起来…
另外我加入了log4j用来打日志
下面是简单演示
大致上是这样
├─sql
├─src
│ └─main
│ ├─java
│ │ └─top
│ │ └─sehnsucht
│ │ ├─dao
│ │ │ └─impl
│ │ ├─service
│ │ │ └─impl
│ │ ├─util
│ │ └─vo
│ └─webapp
│ ├─js
│ ├─layui
│ │ ├─css
│ │ │ └─modules
│ │ │ ├─laydate
│ │ │ │ └─default
│ │ │ └─layer
│ │ │ └─default
│ │ └─font
│ ├─WEB-INF
│ └─webuploader
│ ├─dist
webuploader里面只有dist用到
swfupload
实在是用不了,报错全部解决也不行,搜来搜去选择了WebUploader
,至少是国人写的,好歹文档是中文,不至于看不懂
看着官网的示例有进度条,但是我这里没有,发现是css的问题,然后去百度加进去就好了
用这个组件后台会自动往你写的那个地址传东西,这个是并发的,如果不加锁结果老是不对,所以我在UploadServlet
那里加了锁
使用了layui
来构建前端,包括日期组件也是layui自带的,挺好用的,用那个表单组件的时候差点卡住了,不过问题不大,看文档看懂就好了
从浏览器选择的日期传到后端再进行数据库的查询
我将完整代码放到了
https://gitee.com/hex-cxm/jspQiNiu
有兴趣的可以打个star
我这里只放关键代码,不然太多了
package top.sehnsucht.dao.impl;
import org.apache.log4j.Logger;
import top.sehnsucht.dao.UserPhotoDao;
import top.sehnsucht.util.DBUtil;
import top.sehnsucht.vo.Photo;
import top.sehnsucht.vo.UserInfo;
import top.sehnsucht.vo.UserPhoto;
import java.io.FileInputStream;
import java.sql.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* @Description:
* @Author: Cai
* @CreateTime: 2021/11/12
*/
public class UserPhotoDaoImpl implements UserPhotoDao {
private Logger logger = Logger.getLogger(this.getClass());
/**
* 返回ArrayList>,方便转成json传到前端
* 只有用户信息
*
* @return
*/
@Override
public ArrayList<Map<String, String>> getAllUser() {
Connection conn = null;
PreparedStatement ps = null;
FileInputStream in = null;
ResultSet rs = null;
ArrayList<Map<String, String>> arrs = new ArrayList<>();
try {
conn = DBUtil.getConn();
String sql = "select id,username,birthday from userinfo order by id";
ps = conn.prepareStatement(sql);
rs = ps.executeQuery(sql);
while (rs.next()) {
Map<String, String> map = new HashMap();
Integer id = rs.getInt(1);
String username = rs.getString(2);
java.util.Date birthday = rs.getDate(3);
map.put("id", id.toString());
map.put("username", username);
map.put("birthday",birthday.toString());
arrs.add(map);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
DBUtil.closeConn(conn);
if (null != ps) {
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
return arrs;
}
/**
* 添加photo到数据库中
*
* @param userPhotos
*/
@Override
public void addUserAndPhoto(ArrayList<UserPhoto> userPhotos) {
Connection conn = null;
PreparedStatement ps = null;
try {
conn = DBUtil.getConn();
for (int i = 0; i < userPhotos.size(); i++) {
String sql = "insert into userphoto (userid, photoname, photourl) values (?,?,?)";
ps = conn.prepareStatement(sql);
ps.setInt(1, userPhotos.get(i).getUserid());
ps.setString(2, userPhotos.get(i).getPhotoName());
ps.setString(3, userPhotos.get(i).getPhotoUrl());
int count = ps.executeUpdate();
if (count > 0) {
System.out.println("插入成功!");
} else {
System.out.println("插入失败!");
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
DBUtil.closeConn(conn);
if (null != ps) {
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
/**
* 根据id查找图片集合
*
* @param id
* @return
*/
@Override
public ArrayList<UserPhoto> getPhotoByUserId(Integer id) {
Connection conn = null;
PreparedStatement ps = null;
FileInputStream in = null;
ResultSet rs = null;
ArrayList<UserPhoto> userPhotos = new ArrayList<UserPhoto>();
try {
conn = DBUtil.getConn();
// String sql = "select * from photo where id = " + id;
String sql = "select userid, photoname, photourl from userphoto where userid = " + id;
ps = conn.prepareStatement(sql);
rs = ps.executeQuery(sql);
while (rs.next()) {
UserPhoto userPhoto = new UserPhoto(rs.getInt(1),rs.getString(2),rs.getString(3));
userPhotos.add(userPhoto);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
DBUtil.closeConn(conn);
if (null != ps) {
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
return userPhotos;
}
/**
* 插入用户,返回用户id(主键)
*
* @param userInfo
* @return
*/
@Override
public Integer addUser(UserInfo userInfo) {
Connection conn = null;
PreparedStatement ps = null;
Integer ansId = null;
try {
conn = DBUtil.getConn();
String sql = "insert into userinfo (username,birthday) values(?,?)";
ps = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
ps.setString(1, userInfo.getUsername());
ps.setObject(2, userInfo.getBirthday());
int count = ps.executeUpdate();
if (count > 0) {
System.out.println("插入成功!");
ResultSet rs = ps.getGeneratedKeys();
if (rs.next()) {
//获取主键,设置了主键自增
ansId = rs.getInt(1);
}
} else {
System.out.println("插入失败!");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
DBUtil.closeConn(conn);
if (null != ps) {
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
return ansId;
}
/**
* 根据要求查看用户
* @param name
* @param startDate
* @param endDate
* @return
*/
@Override
public ArrayList<Map<String, String>> getSomeUser(String name, String startDate, String endDate) {
Connection conn = null;
PreparedStatement ps = null;
FileInputStream in = null;
ResultSet rs = null;
ArrayList<Map<String, String>> arrs = new ArrayList<>();
logger.debug("正常进入");
try {
conn = DBUtil.getConn();
String sql = "select id,username,birthday from userinfo where ";
if (name != null && !name.equals("")) {
sql += " username like '%" + name + "%' ";
} else {
sql += " username like '%' ";
}
if (startDate!= null) {
sql += " and birthday >= '" + java.sql.Date.valueOf(startDate) + "'";
}
if (endDate!= null) {
sql += " and birthday <= '" + java.sql.Date.valueOf(endDate) + "'";
}
sql += " order by id ";
logger.info("sql: " + sql);
ps = conn.prepareStatement(sql);
rs = ps.executeQuery(sql);
while (rs.next()) {
Map<String, String> map = new HashMap();
Integer id = rs.getInt(1);
String username = rs.getString(2);
java.util.Date birthday = rs.getDate(3);
map.put("id", id.toString());
map.put("username", username);
map.put("birthday",birthday.toString());
arrs.add(map);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
DBUtil.closeConn(conn);
if (null != ps) {
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
return arrs;
}
}
package top.sehnsucht;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import top.sehnsucht.util.Qiniu;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import org.apache.log4j.Logger;
/**
* @Description:
* @Author: Cai
* @CreateTime: 2021/10/29
*/
public class UploadServlet extends HttpServlet {
private Logger logger=Logger.getLogger(this.getClass());
private Lock lock = new ReentrantLock();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
lock.lock();
try {
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html; charset=UTF-8");
logger.info("单次请求" + req);
//判断文件是否可以上传
boolean isMultipart = ServletFileUpload.isMultipartContent(req);
//可以上传,有问题就报异常
if (isMultipart) {
//创建一个FileItem工厂,通过工厂创建文件上传核心组件ServletFileUpload对象
ServletFileUpload upload = new ServletFileUpload(new DiskFileItemFactory());
try {
//通过核心上传组件解析request请求,获取表单的所有表单项,表单的每一个表单项对应一个FileItem
List<FileItem> items = upload.parseRequest(req);
Iterator<FileItem> it = items.iterator();
for (FileItem item : items) {
if (item.isFormField()) {
logger.error("其他类型");
} else {
String filename = item.getName();
String path = req.getSession().getServletContext().getRealPath("/") + "\\1";
File file = new File(path);
if (!file.exists()) {
file.mkdirs();
}
file = new File(path, filename);
item.write(file);
logger.debug(filename + "上传成功");
Qiniu.uploadPic(filename,path + "\\" + filename);
logger.debug("图片地址为:" + Qiniu.picUrl());
logger.info(filename + "七牛云上传成功");
//把文件名和url存到session中
String allFilename = (String) req.getSession().getServletContext().getAttribute("allFilename");
if (allFilename == null) {
allFilename = "";
}
logger.debug("allFilename" + allFilename);
allFilename = (allFilename + "," + filename);
req.getSession().getServletContext().setAttribute("allFilename", allFilename);
String allPicUrls = (String) req.getSession().getServletContext().getAttribute("allPicUrls");
if (allPicUrls == null) {
allPicUrls = "";
}
logger.debug("allPicUrls" + allPicUrls);
allPicUrls = (allPicUrls + "," + Qiniu.picUrl());
req.getSession().getServletContext().setAttribute("allPicUrls", allPicUrls);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
logger.debug("解锁");
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
package top.sehnsucht;
import org.apache.log4j.Logger;
import top.sehnsucht.dao.UserPhotoDao;
import top.sehnsucht.dao.impl.UserPhotoDaoImpl;
import top.sehnsucht.service.UserPhotoService;
import top.sehnsucht.service.impl.UserPhotoServiceImpl;
import top.sehnsucht.util.DateFormatUtil;
import top.sehnsucht.vo.UserInfo;
import top.sehnsucht.vo.UserPhoto;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
import java.util.ArrayList;
public class JDBCServlet extends HttpServlet {
private Logger logger = Logger.getLogger(this.getClass());
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
logger.debug(req.getSession().getServletContext().getAttribute("allFilename"));
logger.debug(req.getSession().getServletContext().getAttribute("allPicUrls"));
logger.debug(req.getParameter("username"));
logger.debug(req.getParameter("birthday"));
String allFilename = req.getSession().getServletContext().getAttribute("allFilename").toString();
String[] splitFilename = allFilename.split(",");
String allPicUrls = req.getSession().getServletContext().getAttribute("allPicUrls").toString();
String[] splitPicUrls = allPicUrls.split(",");
UserPhotoDao userPhotoDao = new UserPhotoDaoImpl();
UserPhotoService userPhotoService = new UserPhotoServiceImpl(userPhotoDao);
UserInfo userInfo = new UserInfo(req.getParameter("username"), DateFormatUtil.tran(req.getParameter("birthday")));
Integer id = userPhotoService.addUser(userInfo);
ArrayList<UserPhoto> userPhotos = new ArrayList<>();
for (int i = 1; i < splitFilename.length; i++) {
UserPhoto userPhoto = new UserPhoto(id, splitFilename[i], splitPicUrls[i]);
userPhotos.add(userPhoto);
}
userPhotoService.addUserAndPhoto(userPhotos);
String strBackUrl = "http://" + req.getServerName() + ":" + req.getServerPort() + "/list.jsp";
resp.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);
resp.setHeader("Location", strBackUrl);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<%--
Created by IntelliJ IDEA.
User: windows
Date: 2021/10/29
Time: 10:08
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>列表</title>
<link rel="stylesheet" href="${pageContext.request.contextPath}/layui/css/layui.css">
<script src="${pageContext.request.contextPath}/layui/layui.js"></script>
<script src="${pageContext.request.contextPath}/js/jquery-3.6.0.js"></script>
</head>
<body>
<div style="border-radius: 5px;margin-top: 100px;margin-left: 200px;margin-right: 200px">
<form class="layui-form layui-form-pane" action="" id="form-search">
<fieldset class="table-search-fieldset">
<legend>搜索条件</legend>
<div class="layui-form-item">
<div class="layui-inline">
<label class="layui-form-label">姓名:</label>
<div class="layui-input-inline" style="width: 150px;">
<input type="text" name="name" placeholder="请输入姓名" autocomplete="off" class="layui-input">
</div>
<label class="layui-form-label">日期:</label>
<div class="layui-input-inline" style="width: 200px;">
<input id="startDate" type="text" name="startDate" placeholder="起始日期" autocomplete="off" class="layui-input date">
</div>
<div class="layui-form-mid">-</div>
<div class="layui-input-inline" style="width: 200px;">
<input id="endDate" type="text" name="endDate" placeholder="终止日期" autocomplete="off"
class="layui-input date">
</div>
</div>
<button id="btn-search" lay-submit lay-filter="btn-search-filter" type="button" class="layui-btn layui-btn-radius layui-btn-normal">
<i class="layui-icon layui-icon-search"></i>
查询
</button>
<button id="btn-reset" type="reset" class="layui-btn layui-btn-radius layui-btn-primary">
<i class="layui-icon layui-icon-fonts-clear"></i>
清空条件
</button>
</div>
</fieldset>
</form>
<table id="demo" lay-filter="table-pic-filter"></table>
</div>
<script type="text/html" id="col-pic-toolbar">
<a class="layui-btn layui-btn-xs" lay-event="look">查看</a>
</script>
<script>
layui.use(['laydate', 'table', 'form'], function () {
var laydate = layui.laydate;
var table = layui.table;
var form = layui.form;
//表格头部工具栏事件监听
form.on('submit(btn-search-filter)', function(data){
console.log(data.elem) //被执行事件的元素DOM对象,一般为button对象
console.log(data.form) //被执行提交的form对象,一般在存在form标签时才会返回
console.log(data.field) //当前容器的全部表单字段,名值对形式:{name: value}
table.reload('demo', {
where: { //设定异步数据接口的额外参数,任意设
name: data.field.name,
startDate: data.field.startDate,
endDate: data.field.endDate
}
,page: {
curr: 1 //重新从第 1 页开始
}
});
return false; //阻止表单跳转。如果需要表单跳转,去掉这段即可。
});
laydate.render({
elem: '.date' //指定元素
});
table.render({
elem: '#demo'
, height: 312
, url: '/data.jsp' //数据接口
, page: false //关闭分页
, cols: [[ //表头
{field: 'id', title: 'id', width: 100, sort: true, fixed: 'left'}
, {field: 'username', title: 'username', width: 200}
, {field: 'birthday', title: 'birthday', width: 200}
, {title: '操作', align: 'center', toolbar: '#col-pic-toolbar'}
]]
});
table.on('tool(table-pic-filter)', function (obj) {
let data = obj.data;
let layEvent = obj.event;
if (layEvent === 'look') {
console.log(data.name)
console.log("list id: " + data.id);
sessionStorage.setItem("id", data.id)
let url = '/transfer.jsp'
layer.open({
type: 2,
title: "查看图片",
area: ['60%', '60%'],
shadeClose: true,
content: url
});
}
});
});
</script>
</body>
</html>
<%--
Created by IntelliJ IDEA.
User: windows
Date: 2021/10/29
Time: 10:08
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>上传</title>
<link rel="stylesheet" href="${pageContext.request.contextPath}/layui/css/layui.css">
<script src="${pageContext.request.contextPath}/layui/layui.js"></script>
<script src="${pageContext.request.contextPath}/js/jquery-3.6.0.js"></script>
<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/webuploader/dist/webuploader.css">
<script src="${pageContext.request.contextPath}/webuploader/dist/webuploader.js"></script>
<style>
body {
text-align: center;
padding: 20px;
}
form {
width: 500px;
margin: auto;
}
</style>
</head>
<body>
<form method="get" action="${pageContext.request.contextPath}/jdbc" enctype="multipart/form-data" class="layui-form">
<div class="layui-form-item">
<label class="layui-form-label">姓名</label>
<div class="layui-input-block">
<input id="name" type="text" name="username" required placeholder="请输入姓名" autocomplete="off"
class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">生日</label>
<div class="layui-input-block">
<input id="birthday" type="text" name="birthday" required placeholder="请输入生日" autocomplete="off"
class="layui-input">
</div>
</div>
<div class="layui-form-item wu-example" id="uploader">
<label class="layui-form-label"></label>
<div class="layui-input-block" >
<div id="fileList" class="uploader-list"></div>
<div id="filePicker" style="float: left">选择图片</div>
<button id="btn-submit" class="layui-btn" lay-submit lay-filter="*" style="float: right">上传</button>
</div>
</div>
</form>
<script>
layui.use(['laydate'], function () {
let laydate = layui.laydate;
laydate.render({
elem: '[name="birthday"]'
});
});
$(document).ready(function () {
var uploader = WebUploader.create({
// swf文件路径
swf: '/webuploader/dist/Uploader.swf',
// 文件接收服务端。
server: '/upload',
// 选择文件的按钮。可选。
// 内部根据当前运行是创建,可能是input元素,也可能是flash.
pick: '#filePicker',
// 最大上传并发数
thread: 1,
// 只允许选择图片文件。
accept: {
title: 'Images',
extensions: 'gif,jpg,jpeg,bmp,png',
mimeTypes: 'image/*'
},
// 不压缩image, 默认如果是jpeg,文件上传前会压缩一把再上传!
// resize: false,
auto :true
});
// 当有文件添加进来的时候
uploader.on( 'fileQueued', function( file ) {
var $li = $(
'+ file.id + '" class="file-item thumbnail">' +
'' +
'' + file.name + '' +
''
),
$img = $li.find('img');
$list = $('#fileList');
// $list为容器jQuery实例
$list.append( $li );
// 创建缩略图
// 如果为非图片文件,可以不用调用此方法。
// thumbnailWidth x thumbnailHeight 为 100 x 100
uploader.makeThumb( file, function( error, src ) {
if ( error ) {
$img.replaceWith('不能预览');
return;
}
$img.attr( 'src', src );
}, 200, 200 );
});
// 文件上传过程中创建进度条实时显示。
uploader.on( 'uploadProgress', function( file, percentage ) {
var $li = $( '#'+file.id ),
$percent = $li.find('.progress span');
// 避免重复创建
if ( !$percent.length ) {
$percent = $('
')
.appendTo( $li )
.find('span');
}
$percent.css( 'width', percentage * 100 + '%' );
});
// 文件上传成功,给item添加成功class, 用样式标记上传成功。
uploader.on( 'uploadSuccess', function( file ) {
$( '#'+file.id ).addClass('upload-state-done');
});
// 文件上传失败,显示上传出错。
uploader.on( 'uploadError', function( file ) {
var $li = $( '#'+file.id ),
$error = $li.find('div.error');
// 避免重复创建
if ( !$error.length ) {
$error = $('').appendTo( $li );
}
$error.text('上传失败');
});
// 完成上传完了,成功或者失败,先删除进度条。
uploader.on( 'uploadComplete', function( file ) {
$( '#'+file.id ).find('.progress').remove();
});
})
</script>
</body>
</html>
有些用到了有些没用到
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.11version>
<scope>testscope>
dependency>
<dependency>
<groupId>org.junit.jupitergroupId>
<artifactId>junit-jupiterartifactId>
<version>RELEASEversion>
<scope>compilescope>
dependency>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>javax.servlet-apiartifactId>
<version>4.0.1version>
<scope>providedscope>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<version>1.18.18version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>8.0.13version>
dependency>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>jsp-apiartifactId>
<version>2.0version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>fastjsonartifactId>
<version>1.2.76version>
dependency>
<dependency>
<groupId>org.thymeleafgroupId>
<artifactId>thymeleafartifactId>
<version>3.0.12.RELEASEversion>
dependency>
<dependency>
<groupId>commons-fileuploadgroupId>
<artifactId>commons-fileuploadartifactId>
<version>1.2.1version>
<scope>compilescope>
dependency>
<dependency>
<groupId>commons-iogroupId>
<artifactId>commons-ioartifactId>
<version>2.6version>
dependency>
<dependency>
<groupId>com.qiniugroupId>
<artifactId>qiniu-java-sdkartifactId>
<version>7.7.0version>
dependency>
<dependency>
<groupId>com.google.code.gsongroupId>
<artifactId>gsonartifactId>
<version>2.8.5version>
dependency>
<dependency>
<groupId>org.slf4jgroupId>
<artifactId>slf4j-nopartifactId>
<version>1.7.2version>
dependency>
<dependency>
<groupId>log4jgroupId>
<artifactId>log4jartifactId>
<version>1.2.14version>
dependency>
模糊查询日期时间的方法
Java并发编程:Lock
Web Uploader官网
layui镜像文档
等…