zoukankan      html  css  js  c++  java
  • springboot上传文件和下载文件

    springboot上传文件和下载文件

    上传文件

    在这里我们主要有这几个改变:

    1. 使用按钮上传
    2. 放弃form表单上传,使用js上传文件。

    使用按钮上传

    实现效果:

    img

    点击上传模板按钮,弹出文件框:

    img

    刚开始实在是想偷懒,直接百度,结果出来都是一大堆比较麻烦的。后来就自己手动调了。但是提供的思路确实值得借鉴,大概的思路都是:通过将输入框的位置设置可移动的,然后设置透明度为0即可。代码如下:

    <button type="button" th:onclick="batchDelete()" class="btn btn-file btn-sm">
        上传模板
    </button>
    <input class="file" type="file" name="file" onchange="uploadTemplateExcel()"
           style="position: absolute;margin-top: -33px;opacity: 0;margin-left: 219px; 70px">
    

    这样我们就可以使用按钮进行上传文件了。

    使用js上传

    js代码:

    function uploadTemplateExcel(){
        let formData=new FormData();
        formData.append("file",$(".file")[0].files[0]);
        $.ajax({
            type:"POST",
            url:"/xxxx/file/xxxx/upload",
            data:formData,
            cache:false,
            contentType:false,
            processData:false,
            dataType:"json",
            success:function (response) {
                console.log(response);
                if(response !== 0){
                    toastr.success("上传成功","提示:");
                    setTimeout(function () {
                        window.location.reload();
                    },2000)
                }else{
                    toastr.error("上传失败,请重试","提示:");
                }
            }
        })
    }
    

    后端代码

    先说明下我们整体的大概的思路:

    因为我这里只能有一个这个文件,所以处理的时候,可以重复保存,然后在保存的时候,先删除所有之前保存过的文件,然后再保存新的。

    上传的时候,上传文件到服务器,然后再存到数据库里面。

    后台代码已经通过工具类进行封装好了。现在po出:

    FileUploadUtils类:

    package com.linkai.utils.file;
    
    import com.linkai.config.Global;
    import com.linkai.constant.Constants;
    import com.linkai.exception.file.FileNameLengthLimitExceededException;
    
    import com.linkai.exception.file.FileSizeLimitExceededException;
    import com.linkai.exception.file.InvalidExtensionException;
    import com.linkai.utils.DateUtils;
    import com.linkai.utils.uuid.IdUtils;
    import org.apache.commons.io.FilenameUtils;
    import org.apache.commons.lang3.StringUtils;
    import org.springframework.stereotype.Component;
    import org.springframework.web.multipart.MultipartFile;
    
    import java.io.File;
    import java.io.IOException;
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * 文件上传工具类
     * 
     * @author ruoyi
     */
    @Component
    public class FileUploadUtils
    {
        /**
         * 默认大小 50M
         */
        public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024;
    
        /**
         * 默认的文件名最大长度 100
         */
        public static final int DEFAULT_FILE_NAME_LENGTH = 100;
    
        /**
         * 默认上传的地址
         */
        private static String defaultBaseDir = Global.getProfile();
    
        public static void setDefaultBaseDir(String defaultBaseDir)
        {
            FileUploadUtils.defaultBaseDir = defaultBaseDir;
        }
    
        public static String getDefaultBaseDir()
        {
            return defaultBaseDir;
        }
    
        /**
         * 以默认配置进行文件上传
         *
         * @param file 上传的文件
         * @return 文件名称
         * @throws Exception
         */
        public static Map<String, String> upload(MultipartFile file) throws IOException
        {
            try
            {
                return upload(getDefaultBaseDir(), file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
            }
            catch (Exception e)
            {
                throw new IOException(e.getMessage(), e);
            }
        }
    
        /**
         * 根据文件路径上传
         *
         * @param baseDir 相对应用的基目录
         * @param file 上传的文件
         * @return 文件名称
         * @throws IOException
         */
        public static Map<String, String> upload(String baseDir, MultipartFile file) throws IOException
        {
            try
            {
                return upload(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
            }
            catch (Exception e)
            {
                throw new IOException(e.getMessage(), e);
            }
        }
    
        /**
         * 文件上传
         *
         * @param baseDir 相对应用的基目录
         * @param file 上传的文件
         * @param allowedExtension 上传文件类型
         * @return 返回上传成功的文件名
         * @throws FileSizeLimitExceededException 如果超出最大大小
         * @throws FileNameLengthLimitExceededException 文件名太长
         * @throws IOException 比如读写文件出错时
         * @throws InvalidExtensionException 文件校验异常
         */
        public static Map<String,String> upload(String baseDir, MultipartFile file, String[] allowedExtension)
                throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
                InvalidExtensionException
        {
            int fileNamelength = file.getOriginalFilename().length();
            if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH)
            {
                throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
            }
    
            assertAllowed(file, allowedExtension);
            String fileName = extractFilename(file);
    
            File desc = getAbsoluteFile(baseDir, fileName);
            file.transferTo(desc);
            String pathFileName = getPathFileName(baseDir, fileName);
            Map<String, String> map = new HashMap<>();
            map.put("fileName",fileName);
            map.put("pathFileName",desc.getAbsolutePath());
            return map;
        }
    
        /**
         * 编码文件名
         */
        public static final String extractFilename(MultipartFile file)
        {
            String fileName = file.getOriginalFilename();
            String extension = getExtension(file);
            fileName = DateUtils.datePath() + "/" + IdUtils.fastUUID() + "." + extension;
            return fileName;
        }
    
        private static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException
        {
            File desc = new File(uploadDir + File.separator + fileName);
    
            if (!desc.getParentFile().exists())
            {
                desc.getParentFile().mkdirs();
            }
            if (!desc.exists())
            {
                desc.createNewFile();
            }
            return desc;
        }
    
        private static final String getPathFileName(String uploadDir, String fileName) throws IOException
        {
            int dirLastIndex = Global.getProfile().length() + 1;
            String currentDir = StringUtils.substring(uploadDir, dirLastIndex);
            String pathFileName = Constants.RESOURCE_PREFIX + "/" + currentDir + "/" + fileName;
            return pathFileName;
        }
    
        /**
         * 文件大小校验
         *
         * @param file 上传的文件
         * @return
         * @throws FileSizeLimitExceededException 如果超出最大大小
         * @throws InvalidExtensionException
         */
        public static final void assertAllowed(MultipartFile file, String[] allowedExtension)
                throws FileSizeLimitExceededException, InvalidExtensionException
        {
            long size = file.getSize();
            if (DEFAULT_MAX_SIZE != -1 && size > DEFAULT_MAX_SIZE)
            {
                throw new FileSizeLimitExceededException(DEFAULT_MAX_SIZE / 1024 / 1024);
            }
    
            String fileName = file.getOriginalFilename();
            String extension = getExtension(file);
            if (allowedExtension != null && !isAllowedExtension(extension, allowedExtension))
            {
                if (allowedExtension == MimeTypeUtils.IMAGE_EXTENSION)
                {
                    throw new InvalidExtensionException.InvalidImageExtensionException(allowedExtension, extension,
                            fileName);
                }
                else if (allowedExtension == MimeTypeUtils.FLASH_EXTENSION)
                {
                    throw new InvalidExtensionException.InvalidFlashExtensionException(allowedExtension, extension,
                            fileName);
                }
                else if (allowedExtension == MimeTypeUtils.MEDIA_EXTENSION)
                {
                    throw new InvalidExtensionException.InvalidMediaExtensionException(allowedExtension, extension,
                            fileName);
                }
                else
                {
                    throw new InvalidExtensionException(allowedExtension, extension, fileName);
                }
            }
    
        }
    
        /**
         * 判断MIME类型是否是允许的MIME类型
         *
         * @param extension
         * @param allowedExtension
         * @return
         */
        public static final boolean isAllowedExtension(String extension, String[] allowedExtension)
        {
            for (String str : allowedExtension)
            {
                if (str.equalsIgnoreCase(extension))
                {
                    return true;
                }
            }
            return false;
        }
    
        /**
         * 获取文件名的后缀
         * 
         * @param file 表单文件
         * @return 后缀名
         */
        public static final String getExtension(MultipartFile file)
        {
            String extension = FilenameUtils.getExtension(file.getOriginalFilename());
            if (StringUtils.isEmpty(extension))
            {
                extension = MimeTypeUtils.getExtension(file.getContentType());
            }
            return extension;
        }
    }
    

    现在po出后端处理代码:

    /**
     * 基本资料中的商品的模板上传
     *
     * @param file
     * @return
     */
    @RequestMapping(value = "/xxxx/upload", method = RequestMethod.POST)
    @ResponseBody
    public int uploadBackProductInfoUploader(@RequestParam(value = "file") MultipartFile file) {
        try {
            //找出已经存在的数据并且进行删除。
            final HashMap<String, Object> columnMap = new HashMap<>();
            columnMap.put("pro_id",-1);
            imgService.removeByMap(columnMap);
            //保存到服务器上
            Map<String, String> fileUrlInfo  = FileUploadUtils.upload(file);
            //保存到数据库中,这里根据你自己定义构建。
            return fileImgService.save2Db(file,-1,fileUrlInfo);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return 0;
    }
    

    需要注意的是,必须加上@ResponseBody这个注解,要不前端收不到信息。

    到此,上传文件已经完成。


    下载文件

    需要完成的功能

    img

    点击下载模板按钮,完成模板中的下载。

    <button type="button" th:onclick="downloadTemplate()" class="btn btn-file btn-sm">
        下载模板
    </button>
    

    js代码

    因为是用的按钮,所以用js比较好。

    function downloadTemplate(){
        location.href='/admin/file/bproduct/download'
    }
    

    切记:这块不能用ajax异步传输,包括POST、GET方法要不后台不会返回给前台数据,直白点就是浏览器不会有反应,不会出现下载弹框的

    后台代码

    继承org.apache.commons.io.FileUtils的FileUtils工具类:

    package com.linkai.utils.file;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.*;
    import java.net.URLEncoder;
    import java.nio.charset.StandardCharsets;
    
    /**
     * 文件处理工具类
     * 
     * @author ruoyi
     */
    public class FileUtils extends org.apache.commons.io.FileUtils
    {
        public static String FILENAME_PATTERN = "[a-zA-Z0-9_\-\|\.\u4e00-\u9fa5]+";
    
        /**
         * 输出指定文件的byte数组
         * 
         * @param filePath 文件路径
         * @param os 输出流
         * @return
         */
        public static void writeBytes(String filePath, OutputStream os) throws IOException
        {
            FileInputStream fis = null;
            try
            {
                File file = new File(filePath);
                if (!file.exists())
                {
                    throw new FileNotFoundException(filePath);
                }
                fis = new FileInputStream(file);
                byte[] b = new byte[1024];
                int length;
                while ((length = fis.read(b)) > 0)
                {
                    os.write(b, 0, length);
                }
            }
            catch (IOException e)
            {
                throw e;
            }
            finally
            {
                if (os != null)
                {
                    try
                    {
                        os.close();
                    }
                    catch (IOException e1)
                    {
                        e1.printStackTrace();
                    }
                }
                if (fis != null)
                {
                    try
                    {
                        fis.close();
                    }
                    catch (IOException e1)
                    {
                        e1.printStackTrace();
                    }
                }
            }
        }
    
        /**
         * 删除文件
         * 
         * @param filePath 文件
         * @return
         */
        public static boolean deleteFile(String filePath)
        {
            boolean flag = false;
            File file = new File(filePath);
            // 路径为文件且不为空则进行删除
            if (file.isFile() && file.exists())
            {
                file.delete();
                flag = true;
            }
            return flag;
        }
    
        /**
         * 文件名称验证
         * 
         * @param filename 文件名称
         * @return true 正常 false 非法
         */
        public static boolean isValidFilename(String filename)
        {
            return filename.matches(FILENAME_PATTERN);
        }
    
        /**
         * 下载文件名重新编码
         * 
         * @param request 请求对象
         * @param fileName 文件名
         * @return 编码后的文件名
         */
        public static String setFileDownloadHeader(HttpServletRequest request, String fileName)
                throws UnsupportedEncodingException
        {
            final String agent = request.getHeader("USER-AGENT");
            String filename = fileName;
            if (agent.contains("MSIE"))
            {
                // IE浏览器
                filename = URLEncoder.encode(filename, "utf-8");
                filename = filename.replace("+", " ");
            }
            else if (agent.contains("Firefox"))
            {
                // 火狐浏览器
                filename = new String(fileName.getBytes(), "ISO8859-1");
            }
            else if (agent.contains("Chrome"))
            {
                // google浏览器
                filename = URLEncoder.encode(filename, "utf-8");
            }
            else
            {
                // 其它浏览器
                filename = URLEncoder.encode(filename, "utf-8");
            }
            return filename;
        }
    
        /**
         * 下载文件名重新编码
         *
         * @param response 响应对象
         * @param realFileName 真实文件名
         * @return
         */
        public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) throws UnsupportedEncodingException
        {
            String percentEncodedFileName = percentEncode(realFileName);
    
            StringBuilder contentDispositionValue = new StringBuilder();
            contentDispositionValue.append("attachment; filename=")
                    .append(percentEncodedFileName)
                    .append(";")
                    .append("filename*=")
                    .append("utf-8''")
                    .append(percentEncodedFileName);
    
            response.setHeader("Content-disposition", contentDispositionValue.toString());
        }
    
        /**
         * 百分号编码工具方法
         *
         * @param s 需要百分号编码的字符串
         * @return 百分号编码后的字符串
         */
        public static String percentEncode(String s) throws UnsupportedEncodingException
        {
            String encode = URLEncoder.encode(s, StandardCharsets.UTF_8.toString());
            return encode.replaceAll("\+", "%20");
        }
    
        /**
         * 设置文件下载头
         * @param response response
         * @param fileName 文件名
         */
        public static void setFileResponseContent(HttpServletResponse  response,String fileName){
            response.setHeader("content-type", "image/png");
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
        }
    }
    

    这几个方法其实也比较常用的,使用的话,直接类名.就行,不用注解到spring容器中。

    controller

    /**
     * 下载一个样例
     * @param request 请求
     * @param response  响应
     * @return 异常
     * @throws Exception 全局异常
     */
    @RequestMapping(value = "/bproduct/download",method = RequestMethod.GET)
    @ResponseBody
    public String exportSelectedSimpleCases(HttpServletRequest request, HttpServletResponse response) throws Exception{
    
        String filePath= null;
        try {
            request.setCharacterEncoding("UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        filePath = fileImgService.downloadTemplate(request,response);
        return filePath;
    }
    

    service

    /**
     * 下载一个样例
     * @param request request
     * @param response response
     * @return
     */
    String downloadTemplate(HttpServletRequest request, HttpServletResponse response);
    

    serviceImpl

    /**
     * 下载一个样例
     *  @param request  request
     * @param response response
     * @return
     */
    @Override
    public String downloadTemplate(HttpServletRequest request, HttpServletResponse response) {
        //获取文件名
        final QueryWrapper<Img> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("pro_id",-1);
        final Img one = imgService.getOne(queryWrapper);
        OutputStream outputStream = null;
        try {
            outputStream = response.getOutputStream();
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (FileUtils.isValidFilename(one.getImgTitle())) {
            FileUtils.setFileResponseContent(response,one.getImgTitle());
            try {
                FileUtils.writeBytes(one.getImgLocalUrl(),outputStream);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }else{
            System.out.println("下载失败,文件名检验失败!");
            return null;
        }
        return one.getImgLocalUrl();
    }
    

    至此,下载文件也结束了。

    需要注意的也是,必须加上@ResponseBody这个注解,要不不会弹出弹框。

  • 相关阅读:
    上传文件过大的问题FileUploadBase$SizeLimitExceededException
    Oracle分页2
    详解struts2中struts.properties
    Oracle 分页
    Xcode常见错误以及解决方案
    设置时间格式
    UIScrollView解决touchesBegan等方法不能触发的解方案
    ViewController 之间设置转场动画
    IQKeyboredManager使用
    SVN
  • 原文地址:https://www.cnblogs.com/chenyameng/p/14133699.html
Copyright © 2011-2022 走看看