1.录音文件
前台测试代码:
<form id="upload" enctype="multipart/form-data" method="post">
<input type="file" name="file" id="pic"/>
<input type="button" value="提交" onclick="uploadPic();"/>
<span class="showUrl"></span>
<img src="" class="showPic" alt="">
</form>
function uploadPic() {
var form = document.getElementById('upload'),
formData = new FormData(form);
$.ajax({
url:"http://localhost:8080/api/uploadVoiceFile",
type:"post",
data:formData,
processData:false,
contentType:false,
success:function(res){
if(res){
alert(res+"上传成功!");
}
console.log(res);
$("#pic").val("");
$(".showUrl").html(res);
$(".showPic").attr("src",res);
},
error:function(err){
alert("网络连接失败,稍后重试",err);
}
})
}
后台接收文件代码:
发现问题1:
SpringBoot下测试时,发现的该问题,即在解析请求时List list = upload.parseRequest(request);得到的list size=0,也就是根本没有得到文件数据。我在网上搜索该问题的解决方法,大致有以下两种:
(1)原因在于Spring的配置文件中已经配置了MultipartResolver,导致文件上传请求已经被预处理过了,所以此处解析文件列表为空,对应的做法是删除该段配置。
(2)认为是structs的过滤器导致请求已被预处理,所以也要修改对应过滤器的配置。
然而,在SpringBoot下,上述两种解决方法不可能做到,因为SpringBoot的相关配置都是自己完成的,根本没有显示的配置文件。况且以上两种解决方法,修改配置文件可能影响整个工程的其他部分,所以得另寻方案。
我通过断点调试该Controller代码,发现传入的参数HttpServletRequest实例已经为StandardMultipartHttpServletRequest 对象了,且其结构中包含整个form表单的所有字段信息,我就想,区别于网上已有的两种解决方案,总是想避免这种预处理,何不就利用这种预处理,来简化自己的代码结构呢?于是就有了下面的解决代码。其方法很简单,就是对传入的request做强制转型,从而可以根据StandardMultipartHttpServletRequest 实例方法得到相关form表单数据 。
/**
* 上传文件(从request中获取inputstream)
* @param request
* @param response
* @return
* @throws ServletException
* @throws IOException
*/
@ResponseBody
@PostMapping("/uploadVoiceFile")
public void uploadVoiceFile(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
logger.info("进入上传文件uploadVoiceFile方法");
try{
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
String realpath =request.getContextPath()+"/audio/";
String fileName = ""+System.currentTimeMillis();
if (isMultipart) {
File dir = new File(realpath);
if (!dir.exists()){
dir.mkdirs();
}
StandardMultipartHttpServletRequest req = (StandardMultipartHttpServletRequest) request;
Iterator<String> iterator = req.getFileNames();
while (iterator.hasNext()) {
MultipartFile file = req.getFile(iterator.next());
InputStream sis = file.getInputStream();
//存储文件
logger.info("创建音频文件"+request.getContextPath()+fileName+".amr");
FileOutputStream fos = new FileOutputStream(request.getContextPath()+"/audio/"+fileName+".amr");
logger.info("开始写音频文件");
fos.write(file.getBytes()); // 开始写音频文件
fos.flush();
fos.close();
String sourceDir = request.getContextPath()+"/audio/"+fileName+".amr";
String targetDir = request.getContextPath()+"/audio/"+fileName+".mp3";
changeToMp3(sourceDir, targetDir);
response.getWriter().append(fileName);
logger.info("文件地址"+request.getContextPath()+"/audio/"+fileName+".amr");
}
}else{
response.getWriter().append("file not find error");
}
}catch (Exception e) {
e.printStackTrace();
logger.info(e.getMessage());
logger.info(e.getStackTrace().toString());
}
logger.info("退出上传文件uploadVoiceFile方法");
}
发现问题2:
项目需要将 amr 格式的文件转成 mp3格式,网络上提供的思路大多是使用jave-x-x.jar。
这个包确实有用,因为开发时是在windows环境中,测试转换虽然报了异常:
it.sauronsoftware.jave.EncoderException: Duration: N/A, bitrate: N/A
但也确实转换成功了,可以播放。
可是一旦部署到Linux环境当中,不是转换失败,就是转换的文件为大小 0 k。
public static void changeToMp3(String sourceDir,String targetDir) throws InputFormatException {
File source = new File(sourceDir); // 源文件
File target = new File(targetDir); // 目标文件
AudioAttributes audio = new AudioAttributes();
audio.setCodec("libmp3lame");
audio.setBitRate(new Integer(128000));
audio.setChannels(new Integer(2));
audio.setSamplingRate(new Integer(44100));
EncodingAttributes attrs = new EncodingAttributes();
attrs.setFormat("mp3");
attrs.setAudioAttributes(audio);
attrs.setDuration(30.0f);
attrs.setOffset(0f);
Encoder encoder = new Encoder();
try {
encoder.encode(source, target, attrs);
} catch (IllegalArgumentException | EncoderException e) {
e.printStackTrace();
}
}