1.RandomAccessFile(随机文件存取)
pom.xml
<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
long getFilePointer( ):返回文件记录指针的当前位置
void seek(long pos ):将文件指针定位到pos位置
controller
/**
* 大文件上传
*/
@RestController
@RequestMapping("/BigFile")
@CrossOrigin
@Api(value = "大文件分片上传/断点上传", tags = "大文件分片上传/断点上传")
public class BigFileUploadController {
@Autowired
private FileService fileService;
@PostMapping("/")
@ApiImplicitParams({
@ApiImplicitParam(name = "name", value = "文件名", dataType = "String", paramType = "query"),
@ApiImplicitParam(name = "md5", value = "文件名MD5", dataType = "String", paramType = "query"),
@ApiImplicitParam(name = "size", value = "文件大小", dataType = "Long", paramType = "query"),
@ApiImplicitParam(name = "chunks", value = "文件总片数", dataType = "Integer", paramType = "query"),
@ApiImplicitParam(name = "chunk", value = "当前分片片数", dataType = "Integer", paramType = "query"),
@ApiImplicitParam(name = "file", value = "分片文件", dataType = "File", paramType = "query"),
})
@ApiResponse(response = void.class, code = 200, message = "接口返回对象参数")
public void upload(String name, String md5, Long size, Integer chunks, Integer chunk, MultipartFile file) throws IOException {
//判断是不是分片上传 不是很合理实际可以分成2个 请求
if (chunks != null && chunks != 0) {
fileService.uploadWithBlock(name, md5, size, chunks, chunk, file);
} else {
fileService.upload(name, md5, file);
}
}
}
Service
/**
* 分块上传文件
*
* @param md5
* @param size
* @param chunks
* @param chunk
* @param file
* @throws IOException
*/
public void uploadWithBlock(String name,
String md5,
Long size,
Integer chunks,
Integer chunk,
MultipartFile file) throws IOException {
//获取随机生成的文件名
String fileName = getFileName(md5, chunks);
if (name.contains(".")) {
FileUtils.writeWithBlok(UploadConfig.path + fileName + name.substring(name.lastIndexOf(".")), size, file.getInputStream(), file.getSize(), chunks, chunk);
}
FileUtils.writeWithBlok(UploadConfig.path + fileName, size, file.getInputStream(), file.getSize(), chunks, chunk);
addChunk(md5, chunk);
if (isUploaded(md5)) {
removeKey(md5);
fileDao.save(new File(name, md5, UploadConfig.path + fileName, new Date()));
}
}
/**
* 上传文件
*
* @param md5
* @param file
*/
public void upload(String name, String md5, MultipartFile file) throws IOException {
String path = UploadConfig.path + generateFileName() + file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf('.'));
FileUtils.write(path, file.getInputStream());
fileDao.save(new File(name, md5, path, new Date()));
}
工具类
package cn.attackme.myuploader.utils;
import java.io.*;
import java.util.UUID;
/**
* 文件操作工具类
*/
public class FileUtils {
/**
* 写入文件
*
* @param target
* @param src
* @throws IOException
*/
public static void write(String target, InputStream src) throws IOException {
OutputStream os = new FileOutputStream(target);
byte[] buf = new byte[1024];
int len;
while (-1 != (len = src.read(buf))) {
os.write(buf, 0, len);
}
os.flush();
if (os != null) {
os.close();
}
}
/**
* 分块写入文件
*
* @param target
* @param targetSize
* @param src
* @param srcSize
* @param chunks
* @param chunk
* @throws IOException
*/
//FileUtils.writeWithBlok(UploadConfig.path + fileName, size, file.getInputStream(), file.getSize(), chunks, chunk);
public static void writeWithBlok(String target, Long targetSize, InputStream src, Long srcSize, Integer chunks, Integer chunk) throws IOException {
RandomAccessFile randomAccessFile = new RandomAccessFile(target, "rw");
randomAccessFile.setLength(targetSize);
if (chunk == chunks - 1) {
randomAccessFile.seek(targetSize - srcSize);
} else {
randomAccessFile.seek(chunk * srcSize);
}
byte[] buf = new byte[1024];
int len;
while (-1 != (len = src.read(buf))) {
randomAccessFile.write(buf, 0, len);
}
randomAccessFile.close();
}
/**
* 生成随机文件名
*
* @return
*/
public static String generateFileName() {
return UUID.randomUUID().toString();
}
}
上传工具类
/**
* 分块上传工具类
*/
public class UploadUtils {
/**
* 内部类记录分块上传文件信息
*/
private static class Value {
String name;
boolean[] status;
Value(int n) {
this.name = generateFileName();
this.status = new boolean[n];
}
}
private static Map<String, Value> chunkMap = new HashMap<>();
/**
* 判断文件所有分块是否已上传
* @param key
* @return
*/
public static boolean isUploaded(String key) {
if (isExist(key)) {
for (boolean b : chunkMap.get(key).status) {
if (!b) {
return false;
}
}
return true;
}
return false;
}
/**
* 判断文件是否有分块已上传
* @param key
* @return
*/
private static boolean isExist(String key) {
return chunkMap.containsKey(key);
}
/**
* 为文件添加上传分块记录
* @param key
* @param chunk
*/
public static void addChunk(String key, int chunk) {
chunkMap.get(key).status[chunk] = true;
}
/**
* 从map中删除键为key的键值对
* @param key
*/
public static void removeKey(String key) {
if (isExist(key)) {
chunkMap.remove(key);
}
}
/**
* 获取随机生成的文件名
* @param key
* @param chunks
* @return
*/
public static String getFileName(String key, int chunks) {
if (!isExist(key)) {
synchronized (UploadUtils.class) {
if (!isExist(key)) {
chunkMap.put(key, new Value(chunks));
}
}
}
return chunkMap.get(key).name;
}
}
2.文件下载、在线预览
@Controller
@RequestMapping("/file")
public class FileDownload {
/**
* @description:流的形式下载文件
* @author Administrator
* @date: 2021/9/28 Administrator
* @param:response 相应体
* @return:HttpServletResponse
*/
@RequestMapping("/stream")
public HttpServletResponse download(HttpServletResponse response) throws IOException {
String path = "M:\\壁纸\\1.jpg";
OutputStream toClient = null;
InputStream fis = null;
try {
// path是指欲下载的文件的路径。
File file = new File(path);
// 取得文件名。
String filename = file.getName();
// 取得文件的后缀名。
String ext = filename.substring(filename.lastIndexOf(".") + 1).toUpperCase();
// 以流的形式下载文件。
fis = new BufferedInputStream(new FileInputStream(path));
byte[] buffer = new byte[fis.available()];
fis.read(buffer);
// 清空response
response.reset();
// 设置response的Header
response.addHeader("Content-Disposition", "attachment;filename=" + new String(filename.getBytes()));
response.addHeader("Content-Length", "" + file.length());
//获得输出流---通过response获得的输出流 用于向客户端写内容
toClient = new BufferedOutputStream(response.getOutputStream());
response.setContentType("application/octet-stream");
toClient.write(buffer);
toClient.flush();
} finally {
if (fis != null) {
fis.close();
}
if (toClient != null) {
toClient.close();
}
}
return response;
}
/**
* @description:下载网络文件
* @author Administrator
* @date: 2021/9/28 Administrator
* @return:HttpServletResponse
*/
@RequestMapping("/URL")
public void downloadNet() throws MalformedURLException {
int bytesum = 0;
int byteread = 0;
URL url = new URL("https://img-bss.csdnimg.cn/1630907214511.jpg");
try {
URLConnection conn = url.openConnection();
InputStream inStream = conn.getInputStream();
FileOutputStream fs = new FileOutputStream("c:/abc.gif");
byte[] buffer = new byte[1204];
int length;
while ((byteread = inStream.read(buffer)) != -1) {
bytesum += byteread;
System.out.println(bytesum);
fs.write(buffer, 0, byteread);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* @param response 相应体
* @param isOnLine 是否在线预览
* @description:在线浏览或者直接下载文件
* @author Administrator
* @date: 2021/9/28 Administrator
* @return: void
*/
@RequestMapping("/isOnLine")
public void downLoad(HttpServletResponse response, boolean isOnLine) throws Exception {
OutputStream out = null;
BufferedInputStream br = null;
try {
String filePath = "M:\\壁纸\\1.jpg";
File f = new File(filePath);
if (!f.exists()) {
response.sendError(404, "File not found!");
return;
}
br = new BufferedInputStream(new FileInputStream(f));
byte[] buf = new byte[1024];
int len = 0;
// 重写response
response.reset();
if (isOnLine) {
// 在线打开方式
URL u = new URL("file:///" + filePath);
response.setContentType(u.openConnection().getContentType());
response.setHeader("Content-Disposition", "inline; filename=" + f.getName());
// 文件名应该编码成UTF-8
} else {
// 下载方式
response.setContentType("application/x-msdownload");
response.setHeader("Content-Disposition", "attachment; filename=" + f.getName());
}
out = response.getOutputStream();
while ((len = br.read(buf)) > 0)
out.write(buf, 0, len);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (br != null) {
br.close();
}
if (out != null) {
out.close();
}
}
}
}