前端工程中,文件上传 *** 作需要FormData对象的支持;而后端解析则是需要MultipartFile类的支持。
FormDataFormData对象用以将数据编译成键值对,主要用于发送表单数据,但是也可用来发送带键数据(keyed data),而独立于表单使用。而如果enctype属性设置为multipart/form-data,就可以通过form表单的submit()方法来上传数据了。
FornData添加键值对数据FormData提供了append()方法,可以用来添加将要上传的数据,这些数据可以是普通文本数据,也可以是二进制流数据(例如:Blob类型)。
ar formData = new FormData();
formData.append("username", "Groucho");
formData.append("accountnum", 123456); //数字123456会被立即转换成字符串 "123456"
// HTML 文件类型input,由用户选择
formData.append("userfile", fileInputElement.files[0]);
// JavaScript file-like 对象
var content = 'hey!'; // 新文件的正文
var blob = new Blob([content], { type: "text/xml"});
//添加Blob对象
formData.append("webmasterfile", blob);
var request = new XMLHttpRequest();
request.open("POST", "http://foo.com/submitform.php");
request.send(formData);
Blob数据类型
Blob对象表示一个不可变、原始数据的类文件对象,而且Blob是File文件类型的“父级接口”,继承了 blob 的功能并将其扩展使其支持用户系统上的文件。
Blob类型的数据可以按文本或二进制的格式进行读取,也可以转换成 ReadableStream 来用于数据 *** 作。
利用form表单可以提交用户基本信息,此时:enctype采用默认值:application/x-www-form-urlencoded。
当form表单包含type=file的input文件上传控件时,enctype的值就必须要指定为multipart/form-data了,虽然原则上来讲,它仍然具有表单提交基本字符串数据的功能。
在使用FormData上传文件时,需要在表单中添加一个文件类型input。例如:
form表单
如下HTML代码片段,enctype属性被指定为multipart/form-data,可用于上传文件。
Ajax+FormData文件上传
/**
* 上传文件与参数信息
* @param url 请求链接
* @param idSelector id选择器
* @param paramsValue 参数值信息
* */
function uploadFile(url,idSelector,paramsValue) {
//照片-img-id=basic_userPhoto
var filePath=$(idSelector)[0].value;//获取文件路径
var fileObj=$(idSelector)[0].files[0];//获取文件对象
if (filePath){
//获取文件后缀名
var postfix=filePath.substring(filePath.lastIndexOf(".")+1)
if(postfix&&fileObj&&(postfix=="pdf")){
//使用FileReader解析
var pdfFile = $(idSelector)[0].files[0];
//提交文件路径到服务器端程序
var formData = new FormData();
console.log(paramsValue);
formData.append("evidencfile",fileObj);
formData.append("params",JSON.stringify(paramsValue));
$.ajax({
url: url,
method: "POST",
async: true,
data: formData,
processData:false,
contentType:false,
dataType: "json",
success: function (result, status, xhr) {
// console.log("响应信息")
console.log(result)
if(result){
alert(result.message)
//禁用稍后上传菜单
$("#btn_student_award_uploadlater").attr("disabled",true);
$("#btn_student_award_upload").attr("disabled",true);
$("#btn_teacTest_award_uploadlater").attr("disabled",true);
$("#btn_teacTest_award_upload").attr("disabled",true);
}
}
})
}else{
alert("仅支持pdf文件类型!")
}
}
}
基于Servlet的后端解析
基于Servlet的传统开发模式,可以引入第三方jar包,来支持文件上传之后的解析功能开发。
上传文件解析代码截取如下,
/**
* 上传用户头像信息
* @param request
* @return
*/
private Result uploadUserPhoto(HttpServletRequest request) {
//获取session对象
HttpSession session = request.getSession();
//获取当前登录用户
User user = (User) session.getAttribute("login_user");
Result result = null;
//判断是否为文件上传请求
boolean multipartContent = ServletFileUpload.isMultipartContent(request);
System.out.println("isMultipartContent=" + multipartContent);
if (multipartContent) {
//创建文件上传处理对象
ServletFileUpload upload = new ServletFileUpload();
try {
//转换request请求
FileItemIterator itemIterator = upload.getItemIterator(request);
if (itemIterator.hasNext()) {
//获取文件项目
FileItemStream next = itemIterator.next();
//获取请求字段名称
String fieldName = next.getFieldName();
//获取流对象
InputStream inputStream = next.openStream();
System.out.println("inputStream=" + inputStream);
System.out.println("next.isFormField()=" + next.isFormField());
//解析流对象
long rows = userDetailService.uploadPhoto(user.getUsername(), inputStream);
System.out.println("rows=" + rows);
if (rows > 0) {
result = Result.ok("设置成功!");
} else {
result = Result.error("设置失败!");
}
}else {
result = Result.error("设置失败!");
}
} catch (FileUploadException | IOException e) {
e.printStackTrace();
result = Result.error("设置失败!");
}
} else {
result = Result.error("设置失败!");
}
return result;
}
Axios+Element UI
通过Element UI提供的el-upload组件,结合Axios实现文件上传。通常需要:
引入el-upload组件
el-upload事件处理与Axios文件上传
handleAvatarSuccess(res, file, fileList) {
this.imageUrl = URL.createObjectURL(file.raw)
//获取文件对象
let imgFile = file.raw
console.log(imgFile)
if (imgFile) {
//将文件转换为formdata
let formData = new FormData()
let email = localStorage.getItem('email')
formData.append('photo', imgFile) //将文件放入formdata对象
formData.append('email', email)//放入文本键值对
console.log(formData)
//开始上传文件
this.$axios({
url: 'http://localhost:8010/stasys_v3/userDetail/POST/update/photo',
method: 'POST',
data: formData,
})
.then((res) => {
console.log(res)
if (res.data && res.data == 1) {
//头像更新成功
this.$message({
message: '照片更新成功!',
type: 'success',
})
}
})
.catch((err) => {
console.log(err)
//更新失败
this.$message.error('照片更新失败!')
})
} else {
//更新失败
this.$message.error('照片更新失败!')
}
},
handlePictureCardPreview(file) {
// console.log(file)
},
//预处理
beforeAvatarUpload(file) {
const isJPG = file.type === 'image/jpeg'
const isLt2M = file.size / 1024 / 1024 < 2
if (!isJPG) {
this.$message.error('上传头像图片只能是 JPG 格式!')
}
if (!isLt2M) {
this.$message.error('上传头像图片大小不能超过 2MB!')
}
//上传头像至服务器
let fd = new FormData()
let email = localStorage.getItem('email')
fd.append('photo', file) //添加图片
fd.append('email', email) //邮箱参数
return isJPG && isLt2M
},
SSM后端接口编写
SSM框架整合 *** 作就不写了。下面是Mapper、Service、Controller层的代码。其中要被 *** 作的字段是以Blob类型存储在数据库中的。
<update id="updatePhoto" >
UPDATE tb_user_detail SET photo = #{photo}
WHERE userid = #{email}
update>
/**
* 更新头像
* @param email
* @param photo
* @return
*/
public abstract Integer updatePhoto(@Param(value = "email")String email,
@Param(value = "photo")byte[] photo);
Service接口与实现子类
//service接口中抽象方法定义
public interface UserDetailService {
/**
* 更新头像
* @param email
* @param photo
* @return
*/
public abstract Integer updatePhoto(String email,byte[] photo);
}
public interface UserDetailServiceImpl implements UserDetailService {
//properties
@Autowired
private UserDetailMapper mapper;
//methods
@Override
public Integer updatePhoto(String email, byte[] photo) {
return mapper.updatePhoto(email,photo);
}
Controller层与结果响应
@Controller(value = "userDetailController")
@RequestMapping(value = "/userDetail")
public class UserDetailController {
//properties
@Autowired
@Qualifier(value = "userDetailServiceImpl")
private UserDetailService userDetailService;
//methods
@RequestMapping(value = "/POST/update/photo")
@ResponseBody
public Integer updateUserPhoto(@RequestParam("photo")MultipartFile photo,
@RequestParam("email")String email){
byte[] bytes = null;
InputStream inputStream = null;
//接收文件
try {
//转换为二进制byte数组
inputStream = photo.getInputStream();
//获取二进制流文件的字节数
int available = inputStream.available();
bytes= new byte[available];
//读取二进制字节到byte[]数组
int read = inputStream.read(bytes);
inputStream.close();
//更新UserDetail信息
//判断用户是否存在
if (userDetailService.selectOne(email)==null){
//不存在则先增加用户记录
UserDetail userDetail=new UserDetail();
userDetail.setUserid(email);
userDetailService.insertOne(userDetail);
}
//更新头像信息
Integer rows= userDetailService.updatePhoto(email, bytes);
return rows;
} catch (IOException e) {
e.printStackTrace();
return 0;
}
}
}
图片获取
SSM+Vue+Axios+Element UI开发时,文件下载 *** 作:可以将从数据库中读取Blob字段值,编写Mapper接口与XML配置文件,将其自动转换为byte[]字节数组,将其直接返回给前端;最终在前端利用Axios进行解析。
基于Servlet的图片请求传统Servlet开发模式中,可以将从数据库中读取到的byte[]数组,转换为InputStream输入流,通过二进制输入流,配合HttpServletResponse对象的OutputStream对象,将其写出。然后在前端修改img的src属性为后端接口名称,即可实现图片的回显 *** 作。
Servlet代码编写部分代码截取如下,
/*
* 获取用户图像
* */
private void responseUserPhoto(HttpServletRequest req,HttpServletResponse resp) throws IOException {
//获取当前登录用户
HttpSession session = req.getSession();
User user = (User) session.getAttribute("login_user");
InputStream inputStream = userDetailService.downloadPhoto(user.getUsername());
resp.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=UTF-8");
//判断是否获取成功
if (inputStream==null){
PrintWriter writer = resp.getWriter();
writer.write(JSON.toJSONString(Result.error("获取头像失败!")));
writer.flush();
writer.close();
return;
}
resp.setCharacterEncoding("UTF-8");
resp.setContentType("image/jpeg;charset=UTF-8");
OutputStream outputStream = resp.getOutputStream();
byte[] buff=new byte[1024];
int len = -1;
//输出图像
while ((len=inputStream.read(buff))!=-1){
outputStream.write(buff,0,len);
}
//关闭流对象
outputStream.flush();
outputStream.close();
if (inputStream!=null)
inputStream.close();
}
前端代码编写
部分代码截取如下,
假设后端接口为:http://localhost:8010/stasys_v2/get/userphoto.do
基于Axios的图片请求
SSM后端代码编写
Mapper接口与XML中SQL语句编写、Service与子类实现没什么特殊的,只给出Controller接口。
Controller层接口与byte[]类型结果响应@Controller(value = "userDetailController")
@RequestMapping(value = "/userDetail")
public class UserDetailController {
@RequestMapping("/GET/userdetailphoto")
@ResponseBody
public byte[] getPhoto(@RequestParam(value = "email") String email) {
UserDetail userDetail = userDetailService.selectJoin(email);
byte[] photo = userDetail.getPhoto();
return photo;
}
}
Axios前端请求与数据解析
//获取用户照片
axios({
url: 'http://localhost:8010/stasys_v3/userDetail/GET/userdetailphoto',
method: 'GET',
params: { email: "参数值" },
responseType: 'arraybuffer',
})
.then((response) => {
//解析响应对象
console.log(response)
this.imageUrl =
'data:image/png;base64,' +
btoa(
new Uint8Array(response.data).reduce(
(data, byte) => data + String.fromCharCode(byte),
''
)
)
})
.catch((error) => {
console.log(error)
})
至此,图片上传和获取就基本完成了。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)