转载

通用上传下载组件commons-fileupload(基于SpringMVC框架)

SpringMVC框架的文件上传和下载是基于commons-fileupload组件做了进一步封装的通用代码实现

1.导入commons-fileupload.jar包

首先需要maven导入commons-fileupload.jar(自动导入基础包commons-io.jar包)

<!-- 文件上传包 -->
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.3</version>
        </dependency>

2.在SpringMVC配置文件中实现相关配置

<!-- 文件上传解析器 -->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"
        p:defaultEncoding="UTF-8">
        <property name="maxUploadSize" value="2097152" />
        <property name="resolveLazily" value="true" />
    </bean>

这里的文件解析器(multipartResolver)id必须是CommonsMultipartResolver的后单词缩写multipartResolver,不然会导致异常

3.编写上传和下载的工具类UploadUtil

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StreamUtils;
import org.springframework.web.multipart.MultipartFile;

public class UploadUtil {
    public static String basePath = "D://Repositories//uploadFiles//";// 文件上传保存路径
    
    /**
     * 管理上传文件的保存
     * @param file
     * @return 如果保存上传文件成功,则返回新文件名,否则返回空""
     */
    public static String saveFile(MultipartFile file) {
        try {
            // 为防止文件名重复,需要使用随机文件名+文件扩展名,但保存到数据库时应使用原文件名(不可用时间戳,因为在多线程的情况下有可能取到同一个时间戳)
            // 不使用UUID,UUID入库性能并不好
            String extName = file.getOriginalFilename();
            int index = extName.lastIndexOf(".");
            if(index > -1) {
                extName = extName.substring(index);// 这里substring中参数不能为-1否则报异常
            } else {
                extName = "";
            }
            // 随机名+后缀命名并保存到basePath路径下
            String newFileName = Math.random() + extName;
            File newFilePath = new File(basePath + newFileName);
            while(newFilePath.exists()) {
                newFileName = Math.random() + extName;
                newFilePath = new File(basePath + newFileName);
            }
            file.transferTo(newFilePath);
            return newFileName;
        } catch (IllegalStateException | IOException e) {
            e.printStackTrace();
        }
        return "";
    }
    
    public static ResponseEntity<byte[]> downloadFile(String fileName){
        try(InputStream in = new FileInputStream(basePath+fileName)) {
            byte[] body = StreamUtils.copyToByteArray(in);// 将文件流转为字节数组
            HttpHeaders headers = new HttpHeaders();
            MediaType mediaType = MediaType.IMAGE_JPEG;
            headers.setContentType(mediaType);
            HttpStatus status = HttpStatus.OK;
            
            ResponseEntity<byte[]> resp = new ResponseEntity<byte[]>(body,headers,status);// 创建一个HTTPEntity实体,有响应头,响应体,状态码
            return resp;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static void main(String[] args) {

    }
}

UploadUtil的两个核心方法 saveFile(MultipartFile file)downloadFile(String fileName) 分别实现上传和下载文件功能

  • saveFile()
// 生成新的文件File类:"new File(服务器上保存文件的路径+生成的新随机文件名+文件后缀名(基于MultipartFile得到))"
// "file.transferTo(新File类)"表示以新文件类的方式保存到服务器路径上
// 返回新文件名

注意,为什么不用原文件名保存,因为原文件名很容易重名,只有用户要下载时才根据入库的新文件名返回原文件名,同时,使用UUID存文件名影响查询效率,推荐使用随机数或者雪花算法(snowflak)实现全局唯一文件名

  • downloadFile()
// ResponseEntity<byte[]> resp = new ResponseEntity<byte[]>(body,headers,status);// 创建一个HTTPEntity实体并返回,有响应头headers,响应体body,状态码status,根据HTTPEntity实体决定返回的文件表现形式

4.在业务代码中实现相关功能

// 上传文件
    public String uploadFile(MultipartFile file) {
        System.out.println("正在上传文件");
        String result = file.getOriginalFilename();
        System.out.println("原始文件名:" + result);
        result = UploadUtil.saveFile(file);
        System.out.println("保存成功,新文件名:" + result);
        return result;
    }
    
    // 下载文件
    public ResponseEntity<byte[]> downloadFile(String fileName){
        ResponseEntity<byte[]> resp = UploadUtil.downloadFile(fileName);
        return resp;
    }
原文  https://segmentfault.com/a/1190000021364425
正文到此结束
Loading...