当前位置: 首页 > news >正文

【java实现用户编辑上传图片功能】

java实现用户编辑上传图片功能

实现效果

在这里插入图片描述

解决方案

  1. 首先,修改编辑页面的HTML(添加图片上传区域)
    在你的编辑页面HTML中,找到表格部分,在"姓名"字段所在行之后添加头像上传区域。我将把它添加在第一行,紧接在"姓名"字段后面:
<!-- 在表格的tbody中,找到第一个tr(姓名、登录名所在行),在其前面添加以下代码 -->
<tr><td class="d_bg control-label text-info">头像</td><td colspan="3"><div class="avatar-upload"><div class="avatar-preview" ng-if="vm.item.avatarUrl"><img ng-src="{{vm.item.avatarUrl}}" alt="用户头像" onerror="this.style.display='none'; this.nextElementSibling.style.display='inline-block';"><div class="avatar-preview-placeholder" ng-if="false" style="display: none;">未上传头像</div></div><div class="avatar-preview-placeholder" ng-if="!vm.item.avatarUrl">未上传头像</div><div class="upload-btn"><button type="button" class="btn btn-small btn-info" ng-click="vm.triggerFileInput()" style="margin-bottom: 5px;">选择图片</button><input type="file" id="avatarInput" class="upload-input" accept="image/*" onchange="angular.element(this).scope().vm.handleFileSelect(this)"style="display: none;" /></div><div class="image-info" ng-if="vm.item.avatarUrl">已上传头像,点击"选择图片"可更换</div></div></td>
</tr>

然后,将原来的姓名、登录名所在行(第一行)的代码保持不变,它应该紧接在头像上传行之后。
2. 添加CSS样式(确保图片上传区域美观)在你的CSS文件中,或者在页面的

/* 新增的图片上传样式 */
.avatar-upload {margin-bottom: 15px;
}
.avatar-preview {width: 80px;height: 80px;border: 1px solid #ddd;border-radius: 4px;display: inline-block;margin-right: 10px;vertical-align: middle;background-color: #f9f9f9;overflow: hidden;
}
.avatar-preview img {width: 100%;height: 100%;object-fit: cover;
}
.avatar-preview-placeholder {width: 80px;height: 80px;border: 1px solid #ddd;border-radius: 4px;display: inline-block;margin-right: 10px;vertical-align: middle;background-color: #f9f9f9;text-align: center;line-height: 80px;color: #999;font-size: 12px;
}
.upload-btn {display: inline-block;vertical-align: middle;
}
.upload-input {display: none;
}
.image-info {font-size: 12px;color: #666;margin-top: 5px;
}
  1. 修改userEditController控制器(添加图片上传功能)
    在你的userEditController控制器中,添加以下代码来实现图片上传功能。将以下代码添加到控制器的顶部,与其他函数并列:
// 新增:头像相关变量
vm.item.avatarUrl = vm.item.avatarUrl || ''; // 用户头像URL
vm.avatarFile = null; // 选中的头像文件// 新增:触发文件选择
vm.triggerFileInput = function() {var fileInput = document.getElementById('avatarInput');if (fileInput) {fileInput.click();}
};// 新增:文件选择处理
vm.handleFileSelect = function(input) {if (!input || !input.files || input.files.length === 0) {return;}var file = input.files[0];console.log('选择的文件:', file);// 验证文件类型if (!file.type || !file.type.match('image.*')) {toastr.error("请选择图片文件!");return;}// 验证文件大小(例如限制为2MB)if (file.size && file.size > 2 * 1024 * 1024) {toastr.error("图片大小不能超过2MB!");return;}// 显示文件已选择vm.avatarFile = file;toastr.info("图片已选择,点击保存将上传图片");
};// 新增:上传头像到服务器
vm.uploadAvatar = function() {if (!vm.avatarFile) {console.log('没有选择头像文件,跳过上传');return Promise.resolve(); // 如果没有选择文件,直接返回成功的Promise}console.log('开始上传头像文件:', vm.avatarFile);var formData = new FormData();formData.append('file', vm.avatarFile);formData.append('userId', vm.item.userCode || ''); // 使用用户编码作为文件名的一部分return $http.post(window.ContextPath + 'api/upload/user/avatar', formData, {transformRequest: angular.identity,headers: { 'Content-Type': null } // 让浏览器自动设置Content-Type}).then(function(response) {console.log('头像上传响应:', response);if (response.data && response.data.success) {vm.item.avatarUrl = response.data.data.url; // 假设返回的数据中包含图片URLtoastr.success('头像上传成功!');// 保存头像信息到子表return vm.saveUserAvatarToSubTable();} else {throw new Error(response.data.message || '头像上传失败');}}).catch(function(error) {console.error('头像上传失败:', error);toastr.error('头像上传失败,请重试');throw error;});
};// 新增:保存用户头像信息到子表
vm.saveUserAvatarToSubTable = function() {if (!vm.item.userCode || !vm.item.avatarUrl) {return Promise.resolve();}return $http.post(window.ContextPath + 'api/user/avatar/save', {userId: vm.item.userCode,avatarPath: vm.item.avatarUrl,// 其他需要的字段}).then(function(response) {if (response.data && response.data.success) {// 保存成功return response.data;} else {console.warn('用户头像信息保存到子表失败:', response.data);return response.data;}}).catch(function(error) {console.error('用户头像信息保存到子表失败:', error);return Promise.reject(error);});
};// 修改保存方法,整合头像上传功能
var originalSave = vm.save;
vm.save = function() {var a = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;if(vm.item.regEmail){if(!a.test(vm.item.regEmail)){toastr.error("邮箱格式不正确!");return;}}if(!vm.item.primaryUnit){toastr.error("部门不能为空!");return;}if(!vm.item.userRank){toastr.error("职务不能为空!");return;}if(!vm.item.userStation){toastr.error("岗位不能为空!");return;}vm.item.userOrder = 1 //用户排序暂时定为1// 先上传头像,然后保存用户信息vm.uploadAvatar().then(function() {// 头像上传成功或不需要上传头像,继续保存用户信息originalSave.call(vm);}).catch(function(error) {// 头像上传失败,但继续保存用户信息(不包含头像)console.log('继续保存用户信息(不包含头像)');originalSave.call(vm);});
};
  1. 确保在edit函数中正确初始化(在userController中)
    在你的用户列表控制器(userController)中,找到vm.edit函数,确保在打开编辑对话框时正确初始化头像相关属性:
//新增,编辑
vm.edit = function (data) {SystemRestangular.one('userinfo').one(data.userCode).get().then(function (data1) {vm.item = {};Object.assign(vm.item, data1.userInfo, data1.userUnit);// 初始化头像相关属性vm.item.avatarUrl = data1.userInfo.avatarUrl || ''; // 确保avatarUrl属性存在vm.avatarFile = null; // 重置头像文件//0为复星通 ,1为系统if (data.userType == 0) {vm.url = 'modules/permissionManagement/user/userEdit.html';} else {vm.url = 'modules/permissionManagement/user/userEditxt.html';}var dialog = ngDialog.open({template: vm.url,controller: 'userEditController as vm',className: 'ngdialog-theme-default ngdialog-lg',//参数resolve: {item: function () {return vm.item;}}});// 保存估值后添加到列表dialog.closePromise.then(function (data) {if (angular.isObject(data.value)) {vm.query();}});});
}

关键点说明

​​图片预览​​:选择图片后会显示预览,如果上传失败或需要重新选择,可以点击"选择图片"按钮更换。

​​文件验证​​:包含文件类型和大小的验证,确保只允许上传图片且不超过2MB。

​​上传流程​​:点击保存时,先上传头像,然后保存用户信息。如果头像上传失败,仍然会保存用户信息(不包含头像)。

​​后端接口​​:代码中使用了两个后端接口:

window.ContextPath + ‘api/upload/user/avatar’:用于上传头像文件

window.ContextPath + ‘api/user/avatar/save’:用于保存头像路径和相关信息到子表
后端接口:

  1. 接口1: api/upload/user/avatar- 头像文件上传
    功能描述
    接收用户上传的头像图片文件,将文件保存到服务器的指定目录,并返回保存后的文件访问路径。

Controller 实现

package com.yourcompany.hnic.controller;import com.yourcompany.hnic.service.AvatarService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;import java.util.HashMap;
import java.util.Map;@RestController
@RequestMapping("/api/upload/user")
@CrossOrigin(origins = "*") // 根据需要配置CORS
public class UserAvatarUploadController {@Autowiredprivate AvatarService avatarService;/*** 上传用户头像* @param file 头像文件* @param userId 用户ID或用户编码* @return 上传结果*/@PostMapping("/avatar")public ResponseEntity<Map<String, Object>> uploadUserAvatar(@RequestParam("file") MultipartFile file,@RequestParam(value = "userId", required = false) String userId) {Map<String, Object> response = new HashMap<>();try {// 验证文件是否为空if (file.isEmpty()) {response.put("success", false);response.put("message", "上传文件不能为空");return ResponseEntity.badRequest().body(response);}// 验证文件类型(简单验证是否为图片)String contentType = file.getContentType();if (contentType == null || !contentType.startsWith("image/")) {response.put("success", false);response.put("message", "只允许上传图片文件");return ResponseEntity.badRequest().body(response);}// 验证文件大小(例如限制为2MB,2 * 1024 * 1024 bytes)long maxSize = 2 * 1024 * 1024; // 2MBif (file.getSize() > maxSize) {response.put("success", false);response.put("message", "图片大小不能超过2MB");return ResponseEntity.badRequest().body(response);}// 调用服务层上传文件String avatarUrl = avatarService.uploadAvatar(file, userId);// 构建成功响应response.put("success", true);response.put("message", "头像上传成功");Map<String, String> data = new HashMap<>();data.put("url", avatarUrl);// 可选字段// data.put("fileName", fileName);// data.put("filePath", filePath);response.put("data", data);return ResponseEntity.ok(response);} catch (Exception e) {e.printStackTrace();response.put("success", false);response.put("message", "头像上传失败:" + e.getMessage());return ResponseEntity.internalServerError().body(response);}}
}

Service 实现

package com.yourcompany.hnic.service;import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;@Service
public class AvatarService {// 从配置文件中读取上传路径,例如 application.properties 中配置:avatar.upload.path=/uploads/user/avatars/@Value("${avatar.upload.path:/uploads/user/avatars/}")private String uploadPath;/*** 上传头像并返回访问URL* @param file 头像文件* @param userId 用户ID或用户编码* @return 头像的访问URL* @throws IOException*/public String uploadAvatar(MultipartFile file, String userId) throws IOException {// 创建上传目录(如果不存在)File uploadDir = new File(uploadPath);if (!uploadDir.exists()) {uploadDir.mkdirs();}// 生成唯一的文件名,避免文件名冲突String originalFilename = file.getOriginalFilename();String extension = "";if (originalFilename != null && originalFilename.contains(".")) {extension = originalFilename.substring(originalFilename.lastIndexOf("."));}String fileName = UUID.randomUUID().toString() + extension;// 可选:按日期分目录存储,例如 /uploads/user/avatars/2024/01/01/SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd/");String datePath = dateFormat.format(new Date());Path directoryPath = Paths.get(uploadPath + datePath);File dateDir = directoryPath.toFile();if (!dateDir.exists()) {dateDir.mkdirs();}// 完整的文件路径Path filePath = directoryPath.resolve(fileName);// 保存文件Files.copy(file.getInputStream(), filePath);// 构建访问URL,根据你的项目配置调整// 假设你的项目部署在域名下,且上传的文件可以通过相对路径访问// 例如:http://yourdomain.com/uploads/user/avatars/2024/01/01/fileName.jpg// 你需要根据实际情况调整,比如使用Nginx配置静态资源访问,或者使用Spring资源处理器String avatarUrl = "/uploads/user/avatars/" + datePath + fileName;// 如果你的前端和后端分离,可能需要返回完整的URL,如 http://yourdomain.com/uploads/...// 你可以根据需要调整// 例如:String avatarUrl = "http://yourdomain.com" + "/uploads/user/avatars/" + datePath + fileName;return avatarUrl;}
}

配置文件 (application.properties 或 application.yml)
在 src/main/resources/application.properties中添加上传路径配置:

# 头像上传路径
avatar.upload.path=/uploads/user/avatars/

返回数据格式
成功时:

{"success": true,"message": "头像上传成功","data": {"url": "/uploads/user/avatars/2024/01/01/abcdef123456.jpg"}
}

失败时:

{"success": false,"message": "头像上传失败:只允许上传图片文件","data": null
}
  1. 接口2: api/user/avatar/save- 保存用户头像信息到子表
    功能描述
    将用户ID和头像路径保存到用户头像信息子表中,用于记录用户的头像信息。

假设
你有一个用户头像信息表,例如 user_avatar,包含字段如 id, user_code, avatar_path, create_time等。

你需要创建一个对应的 Entity 和 Repository(如果使用 JPA)

Entity 实现

package com.yourcompany.hnic.entity;import javax.persistence.*;
import java.time.LocalDateTime;@Entity
@Table(name = "user_avatar")
public class UserAvatar {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;@Column(name = "user_code", nullable = false)private String userCode;@Column(name = "avatar_path", nullable = false)private String avatarPath;@Column(name = "create_time", nullable = false)private LocalDateTime createTime;// 构造方法public UserAvatar() {}public UserAvatar(String userCode, String avatarPath) {this.userCode = userCode;this.avatarPath = avatarPath;this.createTime = LocalDateTime.now();}// Getter 和 Setter 方法public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getUserCode() {return userCode;}public void setUserCode(String userCode) {this.userCode = userCode;}public String getAvatarPath() {return avatarPath;}public void setAvatarPath(String avatarPath) {this.avatarPath = avatarPath;}public LocalDateTime getCreateTime() {return createTime;}public void setCreateTime(LocalDateTime createTime) {this.createTime = createTime;}
}

Repository 实现

package com.yourcompany.hnic.repository;import com.yourcompany.hnic.entity.UserAvatar;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;import java.util.Optional;@Repository
public interface UserAvatarRepository extends JpaRepository<UserAvatar, Long> {Optional<UserAvatar> findByUserCode(String userCode);
}

Service 实现

package com.yourcompany.hnic.service;import com.yourcompany.hnic.entity.UserAvatar;
import com.yourcompany.hnic.repository.UserAvatarRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.time.LocalDateTime;
import java.util.Optional;@Service
public class UserAvatarService {@Autowiredprivate UserAvatarRepository userAvatarRepository;/*** 保存用户头像信息* @param userCode 用户编码* @param avatarPath 头像路径* @return 保存结果*/public boolean saveUserAvatar(String userCode, String avatarPath) {try {// 查找是否已存在该用户的头像记录Optional<UserAvatar> existingAvatar = userAvatarRepository.findByUserCode(userCode);UserAvatar userAvatar;if (existingAvatar.isPresent()) {// 更新现有记录userAvatar = existingAvatar.get();userAvatar.setAvatarPath(avatarPath);userAvatar.setCreateTime(LocalDateTime.now()); // 可选,根据需求决定是否更新时间} else {// 创建新记录userAvatar = new UserAvatar(userCode, avatarPath);}userAvatarRepository.save(userAvatar);return true;} catch (Exception e) {e.printStackTrace();return false;}}
}

Controller 实现

package com.yourcompany.hnic.controller;import com.yourcompany.hnic.service.UserAvatarService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;import java.util.HashMap;
import java.util.Map;@RestController
@RequestMapping("/api/user/avatar")
@CrossOrigin(origins = "*") // 根据需要配置CORS
public class UserAvatarSaveController {@Autowiredprivate UserAvatarService userAvatarService;/*** 保存用户头像信息* @param request 包含 userId 和 avatarPath* @return 保存结果*/@PostMapping("/save")public ResponseEntity<Map<String, Object>> saveUserAvatar(@RequestBody Map<String, String> request) {Map<String, Object> response = new HashMap<>();try {String userId = request.get("userId");String avatarPath = request.get("avatarPath");// 验证参数if (userId == null || userId.trim().isEmpty()) {response.put("success", false);response.put("message", "用户ID不能为空");return ResponseEntity.badRequest().body(response);}if (avatarPath == null || avatarPath.trim().isEmpty()) {response.put("success", false);response.put("message", "头像路径不能为空");return ResponseEntity.badRequest().body(response);}// 调用服务层保存头像信息boolean saved = userAvatarService.saveUserAvatar(userId, avatarPath);if (saved) {response.put("success", true);response.put("message", "用户头像信息保存成功");// 可选:返回保存的记录信息Map<String, String> data = new HashMap<>();data.put("userId", userId);data.put("avatarPath", avatarPath);response.put("data", data);} else {response.put("success", false);response.put("message", "用户头像信息保存失败");}return ResponseEntity.ok(response);} catch (Exception e) {e.printStackTrace();response.put("success", false);response.put("message", "用户头像信息保存失败:" + e.getMessage());return ResponseEntity.internalServerError().body(response);}}
}

返回数据格式
成功时:

{"success": true,"message": "用户头像信息保存成功","data": {"userId": "USER001","avatarPath": "/uploads/user/avatars/2024/01/01/abcdef123456.jpg"}
}

失败时:

{"success": false,"message": "用户头像信息保存失败:用户ID不能为空","data": null
}
{"success": false,"message": "用户头像信息保存失败","data": null
}

nginx配置

/uploads/user/avatars/2025/09/22/70228fec-ec22-4d97-b72c-99725c47fff9.jpg返回的路径是这个,我用浏览器怎么拼接这个路径显示图片
你返回的图片路径是:

/uploads/user/avatars/2025/09/22/70228fec-ec22-4d97-b72c-99725c47fff9.jpg
这是一个 ​​相对路径​​,它表示图片存储在服务器的某个目录下,但这个路径 ​​不能直接在浏览器中访问​​,除非你正确配置了服务器以提供该路径下的静态资源访问。

server {listen       86;server_name  localhost;location / {add_header Access-Control-Allow-Origin *;add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';if ($request_method = 'OPTIONS') {return 204;}root   D:\ideaworkspace\lygh\page;   index  index.html index.htm;}location /fxtgpt {proxy_pass http://127.0.0.1:8086/fxtgpt;}# 新增:映射 /uploads/ 到服务器上的实际目录location /uploads/ {alias D:/uploads/; # Windows 路径# alias /var/www/uploads/; # Linux 路径}error_page   404  /50x.html;location = /50x.html {root   html;}
}

如果你的图片存储在 D:\uploads\user\avatars\2025\09\22\bbd502cb-aa0a-4b8c-8c12-19d16dc1a43c.jpg,那么:

alias D:/uploads/会将 /uploads/user/avatars/2025/09/22/bbd502cb-aa0a-4b8c-8c12-19d16dc1a43c.jpg映射到 D:\uploads\user\avatars\2025\09\22\bbd502cb-aa0a-4b8c-8c12-19d16dc1a43c.jpg。

如果你的图片存储在其他目录(如 /var/www/uploads/),请将 alias修改为对应的路径。

http://www.dtcms.com/a/400391.html

相关文章:

  • 工业设计灵感网站黄石建设工程信息网
  • 职教集团网站建设方案网页编辑pdf
  • 做创意ppt网站湖南百度推广开户
  • 深圳网站建站建设公司地址美化wordpress后台
  • 网站建设的总体设计自媒体怎么注册
  • 成都市微信网站建电子商务平台网站建设方式
  • 网站浏览器图标怎么做外包活一般是怎么接的
  • 使用DLLM框架对Dream 7B模型在S1K数据集上进行有监督微调
  • linux下gcc升级
  • 卓越职业院校建设专题网站舆情管理
  • 网站建设公司擅自关闭客户网络建立网站定制
  • Python实现手榴弹爆炸算法(Grenade Explosion Method, GEM)(附完整代码)
  • 做wap网站django网站开发规范
  • 百度云网站建设视频甘肃兴城建设有限公司网站
  • 动态分配的UDP_TEST_EQUIPMENT_REQUEST端口
  • todesk远程时出现提示“正在等待对方手动授权”,需要关掉什么设置
  • 深圳网站建设公司佰达网站广告连接如何做
  • 给网站定位提供定制型网站建设
  • 01-基于FPGA和LTC2308的数字电压表设计(总概述)
  • 永川集团网站建设广州正规网站建设
  • 深入理解布隆过滤器
  • 为什么用asp做网站东阳网站建设
  • 【高频电子线路】课上知识点扩展
  • PyQt6+OpenCV 实战:打造功能完备的数字图像处理 GUI 系统
  • 开网站备案流程施工企业组织机构图
  • 特价流量网站网页制作软件免费版无需登录
  • 做暧暖爱视频1000部在线网站做网站的不给源文件
  • 门户网站导航建设方案wordpress 段子主题
  • AnolisOS8.8-没有messages文件
  • 易班网站建设基础云主机 多个网站