点击上传图片按钮,选择要上传的图片,然后发起同步请求,springmvc调用了一个内部的类文件上传解析器去请求体拿文件,封装到MultipartFile中,然后结合七牛云的官方文档写seviceImpl类的方法,返回FileResult对象。
上传相同文件名的图片会怎么样?重复上传同一个图片?会不会造成文件名重复的现象?
会出来,因此我们需要解决。给文件名加一个时间戳,这样就不会出现文件名重复的问题了。
1、表单组件标签只能用
2、上传图片必须采用post请求
图片是二进制数据。上传图片需要将文件数据通过请求体发送到服务器。这样可以保证数据的安全性和完整性。
get请求:参数通过请求头提交到后台,参数放到url后面,而且url长度有限制,长度超限无法提交;而且只能向后台提交文本数据或者字符串数据存在get缓存的问题(可以通过加时间戳来解决这个问题)。GET请求一般用于获取资源,不应该对资源进行修改。效率高,不需要对数据进行封装,减轻了后台处理请求的压力。
post:参数通过请求体提交到后台;能提交文本数据,也能提交二进制数据。对参数长度没有限制,相对安全。post请求一般用于提交数据,会走服务器,因此可能会对服务器资源进行修改。
3、表单的编码格式只能用:enctype=multipart/form-data
根据HTTP协议的规定,浏览器每次向后台提交参数
,都会对参数进行统一编码:默认采用的编码格式是urlencoded,这种编码格式只能对文本数据进行编码,浏览器每次向后台提交参数,都会首先把所有的参数转换成字符串,然后对这些数据统一进行urlencoded编码
,不管前台发的是啥,浏览器把所有的参数统一转换成字符串
,我们拿到的永远也是字符串。
文件上传的表单编码格式只能是:multipart/form-data 多样性的表单数据,阻止默认行为,提交的是什么数据,拿到的是什么数据。没有进行任何的编码。
怎么设置表单的编码格式呢?
前台数据,设置ajax的行为
processDate: false //设置ajax向后台提交参数之前,是否把参数统一转换为字符串:true
contentType:false,//设置ajax向后台提交参数之前,是否把参数的编码统一按urlencoded编码。
请求的方式?异步还是同步?
form表单发送的请求是同步的。浏览器发送的是同步请求。
同步请求只能处理字符串数据。无法解析json对象,无法解析Object
接收文件数据,springmvc专门给我们提供了一个类用来接收客户端上传的文件,MultipartFile
类,当文件传过来后,会自动的将请求体的文件封装到这个类的对象中。
springmvc怎么去拿文件到请求体中?
springmvc调用了一个内部的类去请求体拿文件,封装这个对象。
那一个类一开始没有放在spring(mvc)容器中,要调用这个方法必须创建这个对象,把类的对象创建好,如果没有创建好这个类,他也没法调用方法从请求体中拿到数据封装对象,他会自动去找文件。
这个类是文件上传解析器,将拿到的文件赋值给MultipartFile
第一步:引入插件的配置文件
第二步:创建容器,放入插件
第三步:加载容器,调用工具函数
七牛云官方文档
七牛云是一个云存储服务提供商,可以用于储存和管理大量数据。FilePult.js是一种JavaScript库,可用于将文件上传到云存储服务。七牛云提供了与FilePut.js兼容的API,以便在使用FilePut.js上传文件时,可以将文件上传到七牛云。当使用FilePut.js上传文件时,可以使用七牛云提供的API密钥和密钥等信息进行身份验证,并通过API将文件上传到七牛云。因此,七牛云和FilePut.js之间是一种可以协同工作的关系。
导入maven
<dependency>
<groupId>com.qiniugroupId>
<artifactId>qiniu-java-sdkartifactId>
<version>[7.7.0, 7.10.99]version>
dependency>
<link rel="stylesheet" href="${ctx}/css/fileinput.min.css">link>
<script type="text/javascript" src="${ctx}/js/fileinput.js">script>
<script type="text/javascript" src="${ctx}/js/fileinput_locale_zh.js">script>
在这里我们是将这个表单组件放到了一个from表单里面,form表单都是同步请求。
<tr>
<td>上传商品图片:</td>
<td>
<input type="hidden" name="originalImg" id="originalImg"/>
<form enctype="multipart/form-data">
<input id="file-product" class="file" name="file" type="file" multiple
data-min-file-count="1">
</form>
</td>
</tr>
//================商品-图片上传==================
/**
* 初始设置
* language指定语言
* uploadUrl指定文件上传的后台地址
* allowedPreviewTypes允许上传文件的类型
*/
$('#file-product').fileinput({
language: 'zh',
uploadUrl: '${ctx}/fileUpload/save',
allowedPreviewTypes: ['image', 'html', 'text', 'video', 'audio', 'flash']
});
/**
* 上传文件失败后 调用方法(回调函数)
*/
$('#file-product').on('fileuploaderror', function (event, data, previewId, index) {
var form = data.form,
files = data.files,
extra = data.extra,
response = data.response,
reader = data.reader;
console.log(data);
console.log('File upload error');
});
/**
* 文件错误 比如文件类型错误 调用方法(回调函数)
*/
$('#file-product').on('fileerror', function (event, data) {
console.log(data.id);
console.log(data.index);
console.log(data.file);
console.log(data.reader);
console.log(data.files);
});
/**
* 文件上传成功后 调用方法(回调函数)
*/
$('#file-product').on('fileuploaded', function (event, data, previewId, index) {
var form = data.form,
files = data.files,
extra = data.extra,
response = data.response,
reader = data.reader;
// 服务器文件地址
// alert(data.response.fileUrl);
// 将服务器文件地址设置至隐藏域
$("#originalImg").val(data.response.fileUrl);
console.log('File uploaded triggered');
});
//================商品-图片上传==================
文件返回对象。
*/
public class FileResult implements Serializable {
// success字符串bootstrap file input必须包含该属性
private String success;
// error字符串bootstrap file input必须包含该属性
private String error;
// 描述信息
private String message;
// 文件路径
private String fileUrl;
public String getSuccess() {
return success;
}
public void setSuccess(String success) {
this.success = success;
}
public String getError() {
return error;
}
public void setError(String error) {
this.error = error;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getFileUrl() {
return fileUrl;
}
public void setFileUrl(String fileUrl) {
this.fileUrl = fileUrl;
}
}
@Controller
@RequestMapping("/fileUpload")
public class UploadController {
@Autowired
private UploadService uploadService;
/**
* 将上传的文件赋值给MultipartFile,然后重命名文件,使得每一个文件的名称都不重复,然后调用service方法上传这个文件到后台。
* 返回这个文件的信息,在前端得到响应信息判断文件上传是否成功,渲染页面。
* @param file
* @return
* @throws IOException
*/
@RequestMapping("/save")
@ResponseBody
public FileResult upload(MultipartFile file) throws IOException {
String filename = file.getOriginalFilename();
String date = DateTimeFormatter.ofPattern("yyyy/MM/dd/").format(LocalDateTime.now());
filename = date+System.currentTimeMillis()+filename.substring(filename.lastIndexOf("."));
return uploadService.upload(file.getInputStream(),filename);
}
}
@Service("UploadService")
public class UploadServiceImpl implements UploadService {
@Override
public FileResult upload(InputStream inputStream, String fileName) {
FileResult fileResult = new FileResult();
//构造一个带指定 Region 对象的配置类
Configuration cfg = new Configuration(Region.region2());
//...其他参数参考类注释
UploadManager uploadManager = new UploadManager(cfg);
//...生成上传凭证,然后准备上传,密钥
String accessKey = "3scC_cEM9rkaDmh-Nj7djoprxZMUCwqp47GpspS2";
String secretKey = "GkC1lqSJXoZVwJxtiN-j81CES9uAsqkKMFhwZC5k";
String bucket = "shop-wll";
//默认不指定key的情况下,以文件内容的hash值作为文件名
String key = fileName;
System.out.println("文件上传....");
try {
Auth auth = Auth.create(accessKey, secretKey);
String upToken = auth.uploadToken(bucket);
try {
Response response = uploadManager.put(inputStream,key,upToken,null, null);
//解析上传成功的结果
if (response.statusCode==200){
fileResult.setSuccess("success");
fileResult.setMessage("上传成功");
fileResult.setFileUrl("http://ru4mmztz7.hn-bkt.clouddn.com/"+fileName);
return fileResult;
}else {
fileResult.setError("error");
fileResult.setMessage("上传失败");
return fileResult;
}
} catch (QiniuException ex) {
Response r = ex.response;
System.err.println(r.toString());
fileResult.setError("error");
fileResult.setMessage("上传失败");
try {
System.err.println(r.bodyString());
} catch (QiniuException ex2) {
//ignore
}
}
} catch (Exception ex) {
//ignore
}
return fileResult;
}
}