SpringBoot--文件上传下载

问题

由于第一次使用 spring boot 在开发项目, 在文件上传下载这块 出现了两个BUG:

BUG1: 在服务器Jar包形式下,文件(图片)上传成功后, 浏览器访问不到;

BUG2: 文件下载时, 系统报错:

org.apache.catalina.connector.ClientAbortException: java.io.IOException: 您的主机中的软件终止了一个已建立的连接....

解决方案

我在 Eclipse 中可以实现文件上传,下载,访问, 但项目打成Jar包后,  文件可以上传, 但访问不成功, 导致 访问的图片都加载不到.

附上代码: 

package com.gy.fast.common.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.IOUtils;
import org.springframework.util.ResourceUtils;
import org.springframework.web.multipart.MultipartFile;

import com.gy.fast.common.exception.SysException;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;

/**
 * 文件上传工具
 * 
 * @author geYang
 * @date 2018-06-13
 */
public class UploadUtils {
    /**
     * 文件指定访问URL
     */
    public static final String BASE_URL = "/files/";
    /**
     * 文件指定存放目录
     */
    public static final String BASE_PATH = "uploadfiles/";
    /**
     * 用户图片存放目录
     */
    public static final String USER_IMAGE = "userimage/";
  
    /**
     * 允许上传文件集合
     */
    protected static String[] ALLOW_FORMAT = {
            ".jpg", ".png", ".gif", ".jpeg", ".txt", ".zip",
            ".doc", ".docx", ".xls", ".xlsx"
        };
    /**
     * 获取项目绝对路径
     * @return String( E:\FrindHR\niuniu_lawyer_internal\niuer-law\target\classes )
     * @author geYang
     * @date 2018-06-13 06:47
     * */
    public static String getClassFilePath() {
        try {
            String classPath = ResourceUtils.getURL("classpath:").getPath();
            File classFile = new File(classPath);
            if (!classFile.exists()) {
                classFile = new File("");
            }
            String classFilePath = classFile.getAbsolutePath();
            System.out.println("classFilePath(项目根路径): " + classFilePath);
            return classFilePath;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }
    
    /**
     * 文件存放的绝对路径
     * @param path 默认为 OTHER(other)
     * @author geYang
     * @date 2018-06-13 07:06
     * */
    public static String getUploadFilePath(String path) {
        String classFilePath = getClassFilePath();
        path = CommonUtil.isBlank(path) || path.equals(BASE_URL) || path.equals(BASE_PATH) ? OTHERF : path;
        File uploadFile = new File(classFilePath, BASE_PATH + path);
        if (!uploadFile.exists()) {
            uploadFile.mkdirs();
        }
        String uploadFilePath = uploadFile.getAbsolutePath();
        System.out.println("uploadFilePath(文件上传路径): " + uploadFilePath);
        return uploadFilePath;
    }
    
    
    /**
     * 文件上传
     * @param file 文件
     * @param path 存放目录
     * @author geYang
     * @date 2018-06-13 07:09
     * */
    public static String upload(MultipartFile file, String path) {
        if (file.isEmpty()) {
            return null;
        }
        String oldfileName = file.getOriginalFilename();
        String fileName = getfileName(oldfileName);
        String fileUrl = null;
        try {
            // 文件存放目录
            String uploadFilePath = getUploadFilePath(path);
            uploadFile(file.getBytes(), uploadFilePath, fileName);
            fileUrl = getFileUrl(path, fileName);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return fileUrl;
    }

    /**
     * 获取文件访问路径
     * */
    public static String getFileUrl(String path, String fileName) {
        String fileUrl = BASE_URL + path + fileName;
        System.out.println("fileUrl(文件访问路径): " + fileUrl);
        return fileUrl;
    }
    
    /**
     * 获取文件存放路径(相对路径)
     * @param fileUrl 文件访问路径
     * @return  uploadfiles/outher/08.jpg
     * @author geYang
     * @date 2018-06-13 07:25
     * */
    private static String getUploadPath(String fileUrl) {
        String uploadPath = fileUrl.replace(BASE_URL, BASE_PATH);
        System.out.println("uploadPath(文件存放路径): " + uploadPath);
        return uploadPath;
    }
    
    /**
     * 获取文件存放全路径(绝对)
     * @param fileUrl
     * @return E:\FrindHR\niuniu_lawyer_internal\niuer-law\target\test-classes/uploadfiles/outher/08.jpg
     * @author geYang
     * @date 2018-06-13 07:24
     * */
    public static String getUploadPathAll(String fileUrl) {
        String uploadPathAll = getClassFilePath() + "/" + getUploadPath(fileUrl);
        System.out.println("uploadPathAll(文件存放绝对路径): " + uploadPathAll);
        return uploadPathAll;
    }
    
    /**
     * 生成随机文件名
     * 
     * @param originalName
     * @return
     * @author geYang
     * @date 2018-06-13 10:54
     */
    private static String getfileName(String originalName) {
        String suffix = getSuffix(originalName);
        StringBuffer name = new StringBuffer();
        name.append(DateUtil.format(new Date(), "yyyyMMddHHmmss")).append(RandomUtil.randomString(5)).append(suffix);
        return name.toString();
    }

    /**
     * 获取文件后缀名
     */
    public static String getSuffix(String name) {
        String suffix = name.substring(name.lastIndexOf("."));
        if (!checkSuffix(suffix)) {
            throw new SysException("文件不合法");
        }
        return suffix;
    }
    
    /**
     * 判断文件名是否合格
     * @param name
     * @return
     * @author geYang
     * @date 2018-06-13 08:35
     * */
    public static boolean checkName(String name) {
        return checkSuffix(getSuffix(name));
    }

    /**
     * 校验后缀名是否合法
     * */
    private static boolean checkSuffix(String suffix) {
        Set<String> setSuffix = new HashSet<>(Arrays.asList(ALLOW_FORMAT));
        return setSuffix.contains(suffix);
    }
    
    /**
     * 文件上传
     * */
    public static void uploadFile(byte[] file, String filePath, String fileName) throws IOException {
        File targetFile = new File(filePath);
        if (!targetFile.exists()) {
            targetFile.mkdirs();
        }
        FileOutputStream out = new FileOutputStream(filePath + "/" + fileName);
        out.write(file);
        out.flush();
        out.close();
    }
    
    
    /**
     * 获取文件下载数据
     * @param url
     * @return
     * @author geYang
     * @date 2018-06-13 10:20
     * */
    private static byte[] getDownloadByte(String fileUrl) {
        String uploadPath = getUploadPathAll(fileUrl);
        byte[] data = null;
        try {
            InputStream inputStream = new FileInputStream(new File(uploadPath));
            data = new byte[inputStream.available()];
            inputStream.read(data);
            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
            throw new SysException("文件下载异常");
        }
        return data;
    }

    /**
     * 文件下载
     * @param fileUrl 文件访问路径
     * @param fileName 定义下载文件名,不带后缀
     * @param response
     * @throws IOException
     * @author geYang
     * @date 2018-06-13 10:30
     * */
    public static void download(String fileUrl, String fileName ,HttpServletResponse response) throws IOException {
        // 文件下载
        byte[] DownloadByte = getDownloadByte(fileUrl);
        if (DownloadByte == null) {
            throw new SysException("下载文件不存在");
        }
        response.reset();
        fileName = URLEncoder.encode(fileName.trim()+getSuffix(fileUrl), "UTF-8");
        response.setHeader("Content-Disposition", "attachment; filename=\""+ fileName  +"\"");  
        response.addHeader("Content-Length", "" + DownloadByte.length);  
        response.setContentType("application/octet-stream; charset=UTF-8");
        IOUtils.write(DownloadByte, response.getOutputStream());
    }
    
    
}

/**
 * WebMvc配置
 * @author geYang
 * @date 2018-05-14
 */
@Configuration
public class WebConfig implements WebMvcConfigurer {
    
    @Autowired
    private JwtInterceptor jwtInterceptor;
    
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
    
        // 上传图片访问目录: 
        registry.addResourceHandler(UploadUtils.BASE_URL + "**").addResourceLocations("classpath:/" + UploadUtils.BASE_PATH);
    }
}

文件上传是控制台输出:

classFilePath(项目根路径): E:\testJar
uploadFilePath(文件上传路径): E:\testJar\uploadfiles\userimage
fileUrl(文件访问路径): /files/userimage/20180615160036s4ouv.jpg

这些都是正确的, 在 jar包所在的目录中生成了 uploadfiles/userimage/userimage/20180615160036s4ouv.jpg

证明文件上传是正常的, 但关键就是 访问不到.

如果是Eclipse启动项目, 我能通过

localhost:8080/files/userimage/20180615160036s4ouv.jpg

代码实现

1, 文件上传工具类:

package com.gy.fast.common.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.IOUtils;
import org.springframework.util.ResourceUtils;
import org.springframework.web.multipart.MultipartFile;

import com.gy.fast.common.exception.SysException;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;

/**
 * 文件上传工具
 * 
 * @author geYang
 * @date 2018-06-13
 */
public class UploadUtils {
    /**
     * 文件指定访问URL
     */
    public static final String BASE_URL = "/files/";
    /**
     * 文件指定存放目录
     */
    public static final String BASE_PATH = "uploadfiles/";
    /**
     * 用户图片存放目录
     */
    public static final String USER_IMAGE = "userimage/";
    /**
     * 其他文件存放目录
     */
    public static final String OTHERF = "outher/";
    /**
     * 允许上传文件集合
     */
    protected static String[] ALLOW_FORMAT = {
            ".jpg", ".png", ".gif", ".jpeg", ".txt", ".zip",
            ".doc", ".docx", ".xls", ".xlsx"
        };
    /**
     * 获取项目绝对路径
     * @return String( E:\FrindHR\niuniu_lawyer_internal\niuer-law\target\classes )
     * @author geYang
     * @date 2018-06-13 06:47
     * */
    public static String getClassFilePath() {
        try {
            String classPath = ResourceUtils.getURL("classpath:").getPath();
            File classFile = new File(classPath);
            if (!classFile.exists()) {
                classFile = new File("");
            }
            String classFilePath = classFile.getAbsolutePath();
            System.out.println("classFilePath(项目根路径): " + classFilePath);
            return classFilePath;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 文件存放的绝对路径
     * @param path 默认为 OTHER(other)
     * @author geYang
     * @date 2018-06-13 07:06
     * */
    public static String getUploadFilePath(String path) {
        String classFilePath = getClassFilePath();
        path = CommonUtil.isBlank(path) || path.equals(BASE_URL) || path.equals(BASE_PATH) ? OTHERF : path;
        File uploadFile = new File(classFilePath, BASE_PATH + path);
        if (!uploadFile.exists()) {
            uploadFile.mkdirs();
        }
        String uploadFilePath = uploadFile.getAbsolutePath();
        System.out.println("uploadFilePath(文件上传路径): " + uploadFilePath);
        return uploadFilePath;
    }


    /**
     * 文件上传
     * @param file 文件
     * @param path 存放目录
     * @author geYang
     * @date 2018-06-13 07:09
     * */
    public static String upload(MultipartFile file, String path) {
        if (file.isEmpty()) {
            return null;
        }
        String oldfileName = file.getOriginalFilename();
        String fileName = getfileName(oldfileName);
        String fileUrl = null;
        try {
            // 文件存放目录
            String uploadFilePath = getUploadFilePath(path);
            uploadFile(file.getBytes(), uploadFilePath, fileName);
            fileUrl = getFileUrl(path, fileName);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return fileUrl;
    }

    /**
     * 获取文件访问路径
     * */
    public static String getFileUrl(String path, String fileName) {
        String fileUrl = BASE_URL + path + fileName;
        System.out.println("fileUrl(文件访问路径): " + fileUrl);
        return fileUrl;
    }

    /**
     * 获取文件存放路径(相对路径)
     * @param fileUrl 文件访问路径
     * @return  uploadfiles/outher/08.jpg
     * @author geYang
     * @date 2018-06-13 07:25
     * */
    private static String getUploadPath(String fileUrl) {
        String uploadPath = fileUrl.replace(BASE_URL, BASE_PATH);
        System.out.println("uploadPath(文件存放路径): " + uploadPath);
        return uploadPath;
    }

    /**
     * 获取文件存放全路径(绝对)
     * @param fileUrl
     * @return E:\FrindHR\niuniu_lawyer_internal\niuer-law\target\test-classes/uploadfiles/outher/08.jpg
     * @author geYang
     * @date 2018-06-13 07:24
     * */
    public static String getUploadPathAll(String fileUrl) {
        String uploadPathAll = getClassFilePath() + "/" + getUploadPath(fileUrl);
        System.out.println("uploadPathAll(文件存放绝对路径): " + uploadPathAll);
        return uploadPathAll;
    }

    /**
     * 生成随机文件名
     * 
     * @param originalName
     * @return
     * @author geYang
     * @date 2018-06-13 10:54
     */
    private static String getfileName(String originalName) {
        String suffix = getSuffix(originalName);
        StringBuffer name = new StringBuffer();
        name.append(DateUtil.format(new Date(), "yyyyMMddHHmmss")).append(RandomUtil.randomString(5)).append(suffix);
        return name.toString();
    }

    /**
     * 获取文件后缀名
     */
    public static String getSuffix(String name) {
        String suffix = name.substring(name.lastIndexOf("."));
        if (!checkSuffix(suffix)) {
            throw new SysException("文件不合法");
        }
        return suffix;
    }

    /**
     * 判断文件名是否合格
     * @param name
     * @return
     * @author geYang
     * @date 2018-06-13 08:35
     * */
    public static boolean checkName(String name) {
        return checkSuffix(getSuffix(name));
    }

    /**
     * 校验后缀名是否合法
     * */
    private static boolean checkSuffix(String suffix) {
        Set<String> setSuffix = new HashSet<>(Arrays.asList(ALLOW_FORMAT));
        return setSuffix.contains(suffix);
    }

    /**
     * 文件上传
     * */
    public static void uploadFile(byte[] file, String filePath, String fileName) throws IOException {
        File targetFile = new File(filePath);
        if (!targetFile.exists()) {
            targetFile.mkdirs();
        }
        FileOutputStream out = new FileOutputStream(filePath + "/" + fileName);
        out.write(file);
        out.flush();
        out.close();
    }


    /**
     * 获取文件下载数据
     * @param url
     * @return
     * @author geYang
     * @date 2018-06-13 10:20
     * */
    private static byte[] getDownloadByte(String fileUrl) {
        try {
            String uploadPath = getUploadPathAll(fileUrl);
            InputStream inputStream = new FileInputStream(new File(uploadPath));
            byte[] data = new byte[inputStream.available()];
            inputStream.read(data);
            inputStream.close();
            return data;
        } catch (IOException e) {
            e.printStackTrace();
            throw new SysException("文件下载异常");
        }
    }

    /**
     * 文件下载
     * @param fileUrl 文件访问路径
     * @param fileName 定义下载文件名,不带后缀
     * @param response
     * @throws IOException
     * @author geYang
     * @date 2018-06-13 10:30
     * */
    public static void download(String fileUrl, String fileName ,HttpServletResponse response) throws IOException {
        // 文件下载
        byte[] downloadByte = getDownloadByte(fileUrl);
        if (downloadByte == null) {
            throw new SysException("下载文件不存在");
        }
        int downloadByteLength = downloadByte.length;
        response.reset();
        fileName = URLEncoder.encode(fileName.trim()+getSuffix(fileUrl), "UTF-8");
        response.setHeader("Content-Disposition", "attachment; filename=\""+ fileName  +"\"");  
        response.addHeader("Content-Length", String.valueOf(downloadByteLength));
        response.setContentType("application/octet-stream; charset=UTF-8");
        IOUtils.write(downloadByte, response.getOutputStream());
    }


}

2, 访问文件时 spring boot 路径处理:

/**
 * WebMvc配置
 * @author geYang
 * @date 2018-05-14
 */
@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        // 上传图片访问目录: 如果有权限拦截的话,应该将 (UploadUtils.BASE_URL + "**") 放行
        registry.addResourceHandler(UploadUtils.BASE_URL + "**").addResourceLocations("file:"+ UploadUtils.getClassFilePath()+ "/" + UploadUtils.BASE_PATH);
    }

}

猜你喜欢

转载自blog.csdn.net/singularinty/article/details/80827458