如何使用AngularJS+Spring实现图片上传至服务器文件夹并存储路径到SQL
Hey there! Let's work through your image upload and retrieval problem step by step. I'll break down both the backend (Spring+Hibernate) and frontend (AngularJS) parts, with a focus on fixing that retrieval issue you're stuck on.
First, let's get the upload and database storage working correctly.
1.1 Configure File Upload Support
If you're using traditional Spring MVC, add a MultipartResolver to your XML config to handle file uploads:
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <property name="maxUploadSize" value="5242880"/> <!-- 5MB limit --> </bean>
For Spring Boot, this is auto-configured, but you can tweak limits in application.properties:
spring.servlet.multipart.max-file-size=5MB spring.servlet.multipart.max-request-size=5MB
1.2 Create Hibernate Entity for Image Metadata
Make an entity to store the image's metadata (we'll save the relative path, not the file itself, to the database):
import jakarta.persistence.*; @Entity @Table(name = "images") public class ImageEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(nullable = false) private String fileName; @Column(nullable = false) private String filePath; // Stores relative path, e.g., "uploads/my-image.jpg" // Getters and Setters }
1.3 Write Spring Controller for Upload
This controller will handle the file upload, save it to a server folder, and persist the path to the database:
import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @RestController @RequestMapping("/api/images") @CrossOrigin(origins = "http://your-frontend-domain.com") // Add your frontend URL for CORS public class ImageController { @Value("${image.upload.dir}") // Define this in application.properties private String uploadDir; @PersistenceContext private EntityManager entityManager; @PostMapping("/upload") public String uploadImage(@RequestParam("file") MultipartFile file) throws IOException { // Create upload directory if it doesn't exist Path uploadPath = Paths.get(uploadDir); if (!Files.exists(uploadPath)) { Files.createDirectories(uploadPath); } // Generate a unique filename to avoid overwrites (optional but recommended) String fileName = System.currentTimeMillis() + "_" + file.getOriginalFilename(); Path filePath = uploadPath.resolve(fileName); // Save file to server Files.copy(file.getInputStream(), filePath); // Save metadata to database ImageEntity image = new ImageEntity(); image.setFileName(file.getOriginalFilename()); image.setFilePath(fileName); // Store relative path (or "uploads/" + fileName if needed) entityManager.persist(image); return "Image uploaded successfully!"; } }
Add this to application.properties:
image.upload.dir=/path/to/your/server/images/folder/ # Absolute path, e.g., /var/www/images/
Now let's build the AngularJS part to send the file to the backend.
2.1 HTML Template
Add a file input and upload button:
<div ng-controller="ImageUploadController"> <input type="file" ng-model="file" ng-change="handleFileSelect($event)" accept="image/*"> <button ng-click="uploadImage()" ng-disabled="!file">Upload Image</button> <p>{{uploadStatus}}</p> </div>
2.2 AngularJS Controller
Handle file selection and send the request using FormData:
angular.module('imageApp', []) .controller('ImageUploadController', ['$scope', '$http', function($scope, $http) { $scope.handleFileSelect = function(event) { $scope.file = event.target.files[0]; }; $scope.uploadImage = function() { var formData = new FormData(); formData.append('file', $scope.file); $http.post('http://your-backend-domain.com/api/images/upload', formData, { transformRequest: angular.identity, headers: {'Content-Type': undefined} // Let browser set correct multipart header }).then(function(response) { $scope.uploadStatus = response.data; // Refresh image list here if needed }, function(error) { $scope.uploadStatus = "Upload failed: " + error.data; }); }; }]);
This is where most people get stuck. We need to make the server's image folder accessible via a URL, then use that URL in AngularJS.
3.1 Configure Static Resource Mapping in Spring
We need to map your server's image folder to a public URL path.
For Spring Boot:
Add this to application.properties to expose the upload directory as /images/**:
spring.web.resources.static-locations=file:${image.upload.dir},classpath:/static/
Or use a Java config class:
import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class WebConfig implements WebMvcConfigurer { @Value("${image.upload.dir}") private String uploadDir; @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/images/**") .addResourceLocations("file:" + uploadDir + "/"); } }
For Traditional Spring MVC:
Add this to your XML config:
<mvc:resources mapping="/images/**" location="file:/path/to/your/server/images/folder/"/>
3.2 Retrieve and Display Images in AngularJS
First, create a backend endpoint to fetch image metadata:
@GetMapping("/all") public List<ImageEntity> getAllImages() { return entityManager.createQuery("SELECT i FROM ImageEntity i", ImageEntity.class).getResultList(); }
Then in AngularJS, fetch the metadata and build the image URL:
// In ImageUploadController or a separate controller $scope.getImages = function() { $http.get('http://your-backend-domain.com/api/images/all') .then(function(response) { $scope.images = response.data; // Add full image URL to each object $scope.images.forEach(function(image) { image.fullUrl = "http://your-backend-domain.com/images/" + image.filePath; }); }); }; // Call on controller load $scope.getImages();
Then display the images in HTML:
<div ng-repeat="image in images"> <img ng-src="{{image.fullUrl}}" alt="{{image.fileName}}" style="max-width: 200px;"> <p>{{image.fileName}}</p> </div>
- Folder Permissions: Make sure the server user (e.g., tomcat, www-data) has read/write access to your upload directory.
- Avoid Absolute Paths: Storing relative paths in the database ensures your app works if you move the server or change the upload directory later.
- CORS Issues: If your frontend and backend are on different domains, don't forget the
@CrossOriginannotation or global CORS config in Spring. - File Overwrites: Using a unique filename (like adding a timestamp) prevents existing images from being overwritten by uploads with the same name.
内容的提问来源于stack exchange,提问作者Santhosh M

