Controller 同时接收 MultipartFile数据 以及 json数据
开发中遇到一个接口同时需要接收MultipartFile文件以及其他的json数据,在网上搜索,结果不理想.很多方案觉得无厘头
类似这种:
后来自己也想了一些办法,比较实用的例如(情景见注释):
- 设计两个接口,一个接收MultipartFile文件,一个接收json数据
- 接收MultipartFile文件的接口先执行,服务端解析后,将解析数据存入redis,并返回给前端一个标识key(例如id)
- 前端将json数据以及上个接口返回的标识id通过第二个接口进行请求,进行匹对
后面发现表单提交可以完美解决这一需求:
@PostMapping("/save")
public Response submitVersion(@ModelAttribute @Validated SystemVersionValidate versionValidate) {
@Validated是参数校验类的一个注解,SystemVersionValidate 类中可以接受MultipartFile文件以及你想要的数据
/**
* 版本名称
*/
private String versionName;
/**
* 安卓apk包
*/
private MultipartFile file;
后面还有MultipartFile 转为File的相关操作:
File file = new File(Objects.requireNonNull(multipartFile.getOriginalFilename()));
FileUtils.copyInputStreamToFile(multipartFile.getInputStream(), file);
完整代码:
@PostMapping("/save")
public Response submitVersion(@ModelAttribute @Validated SystemVersionValidate versionValidate) {
MultipartFile multipartFile = versionValidate.getFile();
File file = new File(Objects.requireNonNull(multipartFile.getOriginalFilename()));
Map<String, String> resMap = new HashMap<>();
if (null != multipartFile) {
try {
FileUtils.copyInputStreamToFile(multipartFile.getInputStream(), file);
ApkFile apkFile = new ApkFile(file);
ApkMeta apkMeta = apkFile.getApkMeta();
resMap.put("fileName", apkMeta.getName());
resMap.put("pkgName", apkMeta.getPackageName());
resMap.put("versionCode", apkMeta.getVersionCode().toString());
resMap.put("versionName", apkMeta.getVersionName());
} catch (IOException e) {
e.printStackTrace();
} finally {
file.delete();
}
}
}
附上前端代码:
<head>
<style>
.upload-area {
width: 100px;
height: 100px;
border: 1px dashed #ddd;
border-radius: 5px;
display: inline-flex;
align-items: center;
justify-content: center;
margin: 10px 0;
cursor: pointer;
}
.upload-text {
margin: 10px 5px;
outline-style: none;
border: 1px solid #ccc;
border-radius: 3px;
line-height: 20px;
text-indent: 5px;
}
.upload-button {
display: inline-block;
width: 180px;
height: 40px;
line-height: 40px;
text-align: center;
border: 1px solid #8cc051;
border-radius: 5px;
background: #8cc051;
cursor: pointer;
font-size: 14px;
}
</style>
</head>
<body>
<div id="form">
提交apk文件:<br />
<label id="uploadArea" class="upload-area" for="uploadInput">+</label>
<input name="file" id="uploadInput" type="file" style="display:none;" accept="." onchange="changeInput(this)" />
<br />
名称:<input name="operatorName" id="operatorName" class="upload-text" />
<br />
<button class="upload-button" onclick="submitForm()">提交</button>
</div>
<script>
function changeInput(input) {
document.getElementById('operatorName').value = input.files[0].name;
}
function submitForm() {
var input = document.getElementById('uploadInput')
if (input.files.length > 0) {
var file = input.files[0]
console.dir(file);
var form = document.getElementById('form');
var data = new FormData();
data.append('file', file)
data.append('operatorName', document.getElementById('operatorName').value)
var xhr = new XMLHttpRequest();
// xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 将参数解析成传统form的方式上传
xhr.open('post', 'http://xx.xxx.xxx.xx:8821/version/save', true);
xhr.onload = function () {
alert('上传成功')
};//上传成功事件监听
xhr.onerror = function () {
alert('上传失败')
}; //上传失败事件监听
xhr.send(data);
input.value = "";
} else {
alert('请上传文件')
}
}
</script>
</body>