如何仅用AngularJS、RESTful API和Hibernate实现图片上传:路径存库、文件存本地?
不用Spring,仅用AngularJS + RESTful API(Servlet实现) + Hibernate实现图片上传
核心结论
完全可以实现!不用Spring也没问题——我们可以用原生Java Servlet来实现RESTful风格的文件上传接口,配合Hibernate处理数据库操作,再加上AngularJS做前端上传交互,完全能满足你的需求:图片文件存本地文件夹,路径存数据库。
分步实现指南
1. 前端:AngularJS 文件上传
AngularJS可以用$http结合FormData实现文件上传,无需额外插件,原生方式足够简单:
angular.module('uploadApp', []) .controller('UploadController', function($http) { var vm = this; vm.uploadImage = function() { var formData = new FormData(); formData.append('imageFile', vm.imageFile); // 对应后端接收的参数名 $http.post('/api/upload', formData, { transformRequest: angular.identity, headers: {'Content-Type': undefined} // 让浏览器自动设置正确的multipart/form-data头 }) .then(function(response) { alert('上传成功!图片ID:' + response.data.id); }) .catch(function(error) { alert('上传失败:' + error.data.message); }); }; });
对应的HTML(包含自定义指令让AngularJS识别文件输入):
<div ng-app="uploadApp" ng-controller="UploadController as vm"> <input type="file" file-model="vm.imageFile" /> <button ng-click="vm.uploadImage()">上传图片</button> </div> <script> angular.module('uploadApp').directive('fileModel', ['$parse', function ($parse) { return { restrict: 'A', link: function(scope, element, attrs) { var model = $parse(attrs.fileModel); var modelSetter = model.assign; element.bind('change', function(){ scope.$apply(function(){ modelSetter(scope, element[0].files[0]); }); }); } }; }]); </script>
2. 后端:用Servlet实现RESTful上传接口
因为你不熟悉Spring,我们用原生Java Servlet处理文件上传,需要依赖commons-fileupload和commons-io两个jar包(直接下载放到项目WEB-INF/lib目录即可)。
第一步:配置Servlet(web.xml)
<servlet> <servlet-name>ImageUploadServlet</servlet-name> <servlet-class>com.yourpackage.ImageUploadServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>ImageUploadServlet</servlet-name> <url-pattern>/api/upload</url-pattern> </servlet-mapping>
第二步:实现Servlet逻辑
package com.yourpackage; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; 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.List; public class ImageUploadServlet extends HttpServlet { // 自定义本地图片存储目录,改成你自己的路径 private static final String UPLOAD_DIR = "D:/uploaded_images/"; private SessionFactory sessionFactory; @Override public void init() throws ServletException { // 初始化Hibernate会话工厂 sessionFactory = new Configuration().configure("hibernate.cfg.xml").buildSessionFactory(); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("application/json"); response.setCharacterEncoding("UTF-8"); // 校验是否为文件上传请求 if (!ServletFileUpload.isMultipartContent(request)) { response.getWriter().write("{\"message\":\"不是有效的文件上传请求\"}"); return; } DiskFileItemFactory factory = new DiskFileItemFactory(); ServletFileUpload upload = new ServletFileUpload(factory); try { List<FileItem> items = upload.parseRequest(request); for (FileItem item : items) { if (!item.isFormField()) { // 生成唯一文件名,避免重名覆盖 String fileName = System.currentTimeMillis() + "_" + item.getName(); String filePath = UPLOAD_DIR + fileName; File storeFile = new File(filePath); // 自动创建存储目录(如果不存在) new File(UPLOAD_DIR).mkdirs(); // 保存文件到本地 item.write(storeFile); // 用Hibernate将路径存入数据库 Session session = sessionFactory.openSession(); session.beginTransaction(); ImageEntity image = new ImageEntity(); image.setImagePath(filePath); image.setFileName(fileName); Long imageId = (Long) session.save(image); session.getTransaction().commit(); session.close(); // 返回成功响应 response.getWriter().write("{\"id\":" + imageId + ",\"message\":\"上传成功\"}"); return; } } } catch (Exception e) { response.getWriter().write("{\"message\":\"上传失败:" + e.getMessage() + "\"}"); e.printStackTrace(); } } @Override public void destroy() { // 关闭Hibernate会话工厂 sessionFactory.close(); } }
3. Hibernate配置与实体类
第一步:Hibernate配置文件(hibernate.cfg.xml,放在src/main/resources下)
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!-- 替换成你的数据库连接信息 --> <property name="hibernate.connection.driver_class">com.mysql.cj.jdbc.Driver</property> <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/your_db?useSSL=false&serverTimezone=UTC</property> <property name="hibernate.connection.username">root</property> <property name="hibernate.connection.password">your_pwd</property> <property name="hibernate.dialect">org.hibernate.dialect.MySQL8Dialect</property> <property name="hibernate.show_sql">true</property> <property name="hibernate.hbm2ddl.auto">update</property> <!-- 自动生成数据库表 --> <!-- 注册实体类 --> <mapping class="com.yourpackage.ImageEntity"/> </session-factory> </hibernate-configuration>
第二步:图片实体类(ImageEntity.java)
package com.yourpackage; import javax.persistence.*; @Entity @Table(name = "images") public class ImageEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(name = "file_name") private String fileName; @Column(name = "image_path") private String imagePath; // 空构造函数、getter和setter public ImageEntity() {} public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getFileName() { return fileName; } public void setFileName(String fileName) { this.fileName = fileName; } public String getImagePath() { return imagePath; } public void setImagePath(String imagePath) { this.imagePath = imagePath; } }
注意事项
- 确保本地存储文件夹有读写权限,否则文件保存会失败。
- 生成唯一文件名很重要,避免同名文件覆盖。
- 如果部署到服务器,建议用相对路径或环境变量配置存储目录,不要写死绝对路径。
- 别忘记添加
commons-fileupload和commons-io的jar包到项目中,否则Servlet无法解析文件上传请求。
内容的提问来源于stack exchange,提问作者Aakriti Gupta
相关产品推荐
相关产品推荐

