這學期JAVAEE課程做了個項目,其中有個功能是在前端輸入文本及選擇文件,將這些文本和文件傳到MySQL里。查了資料,先后用兩種方式實現。難點在於如何把前端input標簽file類型的文件取到。這里記錄了【兩種上傳文件到指定目錄的方式】和【項目展示:JSP實現上傳文件到MySQL】。
參考資料
[1] Java+mysql本地圖片上傳數據庫及下載示例
[2] 使用Servlet3.0提供的API實現文件上傳到指定位置
上傳文件方式一
先來講第一種方式,在項目后期被第二種方式取代了,原因后續會說到。最開始查到了這部分代碼,雖然實現了上傳指定路徑的文件到數據庫中,但是得去改瀏覽器設置。如果不改,獲取出來的路徑是這樣的:C:\fakepath\文件名。顯而易見,獲取到的是一個不存在的路徑。原因很簡單:出於安全性考慮,文件路徑可能會暴露你的用戶名或者其他內容,瀏覽器通過fakepath直接代替了其中的路徑名,保護用戶隱私。有一個解決辦法,不過僅限IE瀏覽器。打開瀏覽器,在菜單欄依次點擊:工具 -> Internet選項 -> 安全 -> 自定義級別 -> 找到“其他”中的“將本地文件上載至服務器時包含本地目錄路徑”,選中“啟用”即可。但作為開發者,我們不能指望用戶去這么做,應該通過代碼解決這個問題。
上傳文件方式二
后續查找資料並沒有找到有效可用的代碼,於是去請教了老師。老師給我提供了一種思路:使用Servlet3.0提供的API,實現文件上傳到指定文件夾,再獲取該文件的名稱,然后加上之前指定的路徑,就可以得到該文件的絕對路徑了,最后再把文件傳到MYSQL中。上傳文件至指定目錄的代碼可參考資料2。
項目展示
Dynamic Web Project項目結構如下,值得注意的是用到了mysql-connector-java-5.1.46.jar,這里准備了網上分享的鏈接,沒有的話先去下載
建立數據庫和表
先准備一個數據庫和表,這里我用的庫名是fileDB,表名是files,以下是建表腳本
CREATE TABLE files (
id INT NOT NULL,
-- 文件ID
content VARCHAR (100) NULL,
-- 文件描述
file1 LONGBLOB NULL,
-- 文件源1
file2 LONGBLOB NULL,
-- 文件源2
PRIMARY KEY (id)
);
index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()
+ path + "/";
%>
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP to MySQL</title>
</head>
<body>
<form id="myform" name="myform"
action="${pageContext.request.contextPath}/UploadFile" method="post"
enctype="multipart/form-data">
文件描述 <br> <input id="content" name="content" type="text"><br>
文件1 <br> <input id="file1" name="file" type="file" value="選擇文件"><br>
文件2 <br> <input id="file2" name="file" type="file" value="選擇文件"><br>
<input id="form_submit" name="form_submit" type="submit" value="上傳"
onclick="submit()">
</form>
</body>
</html>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0">
<display-name>JSPtoMySQL</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
JDBC.java
package Conn;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class JDBC {
// jdbc四大參數,記得修改MySQL的用戶名和密碼
static final public String driver = "com.mysql.jdbc.Driver";
static final public String url = "jdbc:mysql://localhost:3306/filedb?useSSL=false";
static final public String username = "root";
static final public String password = "root";
static Connection conn = null;
static PreparedStatement ps = null;
static ResultSet rs = null;
static {
try {
Class.forName(driver);
} catch (ClassNotFoundException e) {
e.printStackTrace();
throw new RuntimeException();
}
}
public int getNewID() {
String sql = "select MAX(id) from files";
int id = -1;
try {
conn = DriverManager.getConnection(url, username, password);
ps = conn.prepareStatement(sql);
rs = ps.executeQuery();
while (rs.next())
{
id = rs.getInt("MAX(id)");
}
System.out.println("getMAXID="+id);
return id + 1;
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
} finally {
close(conn, ps, rs);
}
}
public void insert(int id, String content) {
String sql = "insert into files(" + "id, content) " + "values (" + "?, ?);";
try {
conn = DriverManager.getConnection(url, username, password);
ps = conn.prepareStatement(sql);
ps.setInt(1, id);
ps.setString(2, content);
ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
} finally {
close(conn, ps, null);
}
}
public int upload_file(int id, String fileUrl, int flag) {
String sql = "";
// 區分上傳的是文件1還是文件2
if (flag == 1) {
sql = "update files set " + "file1 = ? " + "where id = " + id + ";";
} else if (flag == 2) {
sql = "update files set " + "file2 = ? " + "where id = " + id + ";";
}
FileInputStream fis = null;
// 讀取文件
File file = new File(fileUrl);
// 記錄被影響的行數
int success = 0;
try {
// 轉換文件為字節流
fis = new FileInputStream(file);
conn = DriverManager.getConnection(url, username, password);
ps = conn.prepareStatement(sql);
ps.setBlob(1, fis);
success = ps.executeUpdate();
System.out.println("受影響的行:"+success);
return success;
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
} finally {
close(conn, ps, null);
}
}
// 回收資源
public void close(Connection conn, PreparedStatement ps, ResultSet rs) throws RuntimeException {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
if (ps != null) {
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
}
UploadFile.java
package servlet;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collection;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import Conn.JDBC;
//使用@WebServlet配置UploadFile的訪問路徑
@WebServlet(name = "UploadFile", urlPatterns = "/UploadFile")
//使用注解@MultipartConfig將一個Servlet標識為支持文件上傳
@MultipartConfig // 標識Servlet支持文件上傳
public class UploadFile extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("UploadFile開始工作");
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
JDBC jdbc = new JDBC();
int id = jdbc.getNewID();
String content = request.getParameter("content");
System.out.println("UploadFile獲取到的id:" + id);
System.out.println("UploadFile獲取到的content:" + content);
// 將JSP接收到的文本類型數據插入到數據庫中
jdbc.insert(id, content);
/* 以下代碼的作用:上傳文件到指定目錄,並插入到數據庫中 */
// 存儲路徑
String savePath = request.getServletContext().getRealPath("/WEB-INF/uploadFile");
// 判斷文件夾是否存在
File file = new File(savePath);
// 如果文件夾不存在則創建
if (!file.exists() && !file.isDirectory()) {
file.mkdir();
System.out.println(savePath + "已創建");
} else {
System.out.println(savePath + "已存在");
}
// 獲取上傳的文件集合
Collection<Part> parts = request.getParts();
System.out.println("parts.size="+parts.size());
// num用於標識和記錄當前處理的第n個文件,success用於記錄成功插入文件的次數
int num = 1;
int success = 0;
for (Part part : request.getParts()) {
// 只處理上傳文件區段
if (part.getName().startsWith("file")) {
String fileName = getFileName(part);
// 防止只上傳文件2,不上傳文件1出現的bug
if (fileName.length()==0) {
num++;
continue;
}
// 把文件寫到指定路徑
part.write(savePath + File.separator + fileName);
String fileUrl = savePath + "\\" + fileName;
System.out.println(fileName+"已上傳");
// 向數據庫表中插入兩個文件
success += jdbc.upload_file(id, fileUrl, num++);
}
}
PrintWriter out = response.getWriter();
out.println("數據插入成功,其中包括" + success + "個文件");
//response.sendRedirect("index.jsp");
out.flush();
out.close();
}
private String getFileName(Part part) {
String header = part.getHeader("Content-Disposition");
String fileName = header.substring(header.indexOf("filename=\"") + 10, header.lastIndexOf("\""));
header.lastIndexOf("\"");
return fileName;
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}