文件上传时遇到 “File has been moved - cannot be read again”
出现该异常是在调用file.getBytes()时,网上也有在调用file.getInputStream()时也会出现该异常。经阅读相关文章资料,该异常会在多线程时偶尔出现,单线程不会出现,原因与上传文件大小有关,有的提出修改文件上传相关参数大小,以springboot项目为例:在application.properties配置文件中添加配置:spring.http.multipart.maxFi
·
出现该异常是在调用 file.getBytes()时,网上也有在调用file.getInputStream()时也会出现该异常。经阅读相关文章资料,该异常会在多线程时偶尔出现,单线程不会出现,原因与上传文件大小有关,有的提出修改文件上传相关参数大小,以springboot项目为例:
在application.properties
配置文件中添加配置:
spring.http.multipart.maxFileSize=10Mb // 设置单个文件的大小
spring.http.multipart.maxRequestSize=10Mb // 设置总上传的数据大小
10MB时默认值,而我调到100MB都没用。
贴出相关代码:
CompletableFuture.supplyAsync(() -> { //CompletableFuture.supplyAsync() java8 的异步调用函数
List<FileUploadLog> fileUploadLogs = files.stream().map(file -> {
FileOutputStream out = null;
FileUploadLog fileUploadLog = null;
try {
String filePath = StaticV.FILE_PATH + File.separator + StaticV.IMG_DIR + File.separator + LocalDate.now() + File.separator;
String fileName = System.currentTimeMillis()+"_"+file.getOriginalFilename();
File newFile = new File(filePath);
if (!newFile.exists()) {
newFile.mkdirs();
}
out = new FileOutputStream(filePath + fileName);
out.write(file.getBytes()); //file.getBytes() 会抛出该异常
String suffix = fileName.substring(fileName.lastIndexOf("."));
File tempFile = File.createTempFile(String.valueOf(System.currentTimeMillis()), suffix);
FileInputStream inputStream = new FileInputStream(filePath + fileName);
FileUtils.copyInputStreamToFile(inputStream, tempFile);
BufferedImage bufferedImage = ImageIO.read(tempFile);
Map<String, String> tempMap = new HashMap<>();
if (bufferedImage != null) {
tempMap.put("height", String.valueOf(bufferedImage.getHeight()));
tempMap.put("width", String.valueOf(bufferedImage.getWidth()));
}
******************************以下省略
*
解决办法:
List<String> fileNames = files.stream().map(file -> {
String fileName = System.currentTimeMillis()+"_"+file.getOriginalFilename();
try {
saveFileBytesToRedis(file.getBytes(),fileName); //获取文件将文件转换成byte[]数组,进行分包存储到redis
} catch (IOException e) {
e.printStackTrace();
}
return fileName;
}).collect(Collectors.toList());
CompletableFuture.supplyAsync(() -> {
List<FileUploadLog> fileUploadLogs = fileNames.stream().map(fileName -> {
FileOutputStream out = null;
FileUploadLog fileUploadLog = null;
try {
String filePath = StaticV.FILE_PATH + File.separator + StaticV.IMG_DIR + File.separator + LocalDate.now() + File.separator;
File newFile = new File(filePath);
if (!newFile.exists()) {
newFile.mkdirs();
}
out = new FileOutputStream(filePath + fileName);
out.write(getFileBytesRedisKey(fileName)); //从redis中分包取值进行byte[]数组合并解析音频
String suffix = fileName.substring(fileName.lastIndexOf("."));
File tempFile = File.createTempFile(String.valueOf(System.currentTimeMillis()), suffix);
FileInputStream inputStream = new FileInputStream(filePath + fileName);
FileUtils.copyInputStreamToFile(inputStream, tempFile);
BufferedImage bufferedImage = ImageIO.read(tempFile);
Map<String, String> tempMap = new HashMap<>();
if (bufferedImage != null) {
tempMap.put("height", String.valueOf(bufferedImage.getHeight()));
tempMap.put("width", String.valueOf(bufferedImage.getWidth()));
}
****************以下省略
文件上传操作redis的相关方法:
/**
* 获取文件将文件转换成byte[]数组,进行分包存储到redis
*/
public synchronized void saveFileBytesToRedis(byte[] buffer,String fileName) {
log.info("filename========================"+fileName);
int viceLength = 180; //每个字节包大小
int viceNumber = (int) Math.ceil(buffer.length /(double) viceLength);//存多少个包
int from, to;
List listrk = new ArrayList();
for (int i=0;i<viceNumber;i++){ //将完整音频buffer[]进行循环拆分
from=i*viceLength;
to=from+viceLength;
if(to>buffer.length)
to=buffer.length;
listrk.add(Arrays.copyOfRange(buffer,from,to));//按字节范围拷贝生成新数组,添加到List列表中
}
redisTemplate.opsForList().rightPushAll(StaticV.FILE_UPLOAD_FILE_BYTES + fileName, listrk);//redisTemplate的批量添加,以List列表形式进行存储
//TODO 可用定时任务定期清理redis中的图片缓存
}
/**
* 从redis中分包取值进行byte[]数组合并解析音频
*/
public byte[] getFileBytesRedisKey(String fileName) {
List list =redisTemplate.opsForList().range(StaticV.FILE_UPLOAD_FILE_BYTES + fileName, 0, -1); //通过key获取指定区间的值,List方式存储用List集合去接收
//合并音频
List<byte[]> blist = list;
int lengthTotal = 0;
for (byte[] item : blist) {
lengthTotal += item.length;
}
byte[] totalByte = new byte[lengthTotal];
int begin = 0;
for (byte[] item : blist) {
//System.arraycopy(原数组, 原数组起始位置, 目标数组, 目标数组起始位置, 复制长度);
System.arraycopy(item, 0, totalByte, begin, item.length);
begin += item.length;
}
return totalByte; //OutputStream对象输出流,直接返回为空,浏览器自动会为我们解析音频流
}
经过这样处理,不会出现该异常。
更多推荐
已为社区贡献2条内容
所有评论(0)