springboot文件上传(图片)

springboot文件上传(图片)

坑坑坑
	在上传过后的文件命名时,尽量不要是带上源文件名!!!
	正确写法是: String filenameUUID = UUID.randomUUID().toString().replace("-", "")+".zip";
	错误写法是: String filenameUUID = UUID.randomUUID().toString().replace("-", "")+originalFileName;
	因为:带上原始的文件名,有可能原始的文件名,会是带上特殊字符.
线上springboot文件上传,过了一段时间报错!
	原因:
    spring boot的应用服务在启动的时候,会生成在操作系统的/tmp目录下生成一个Tomcat.*的文件目录,用于"java.io.tmpdir"文件流操作  
    程序对文件的操作时:会生成临时文件,暂存在临时文件中;
    lunix 系统的tmpwatch 命令会删除10天未使用的临时文件;
    长时间不操作,导致/tmp下面的tomcat临时文件目录被删除,且删除的文件不可恢复,上传文件时获取不到文件目录,报错
	{"timestamp":1552273330708,"status":500,
	"error":"Internal Server Error",
	"exception":"org.springframework.web.multipart.MultipartException",
	"message":"Could not parse multipart servlet request; nested exception is java.io.IOException: 
	The temporary upload location [/tmp/tomcat.1756970833364702281.8080/work/Tomcat/localhost/api] is not valid",
	"path":"/api/file/upload-picture"}

	解决
	自己选择了添加配置这种方案
	server.tomcat.basedir=/data/tms/tmp/tomcat

	线上部署操作
		一: 拷贝,备份
		cp application.properties bk-2019312application.properties
	
	二: vi编辑器
		vi application.properties
	
	三: 可编辑
		i
		
	四: 添加配置
		server.tomcat.basedir=/data/tms/tmp/tomcat
	
	五: 杀死进程
		ps -ef | grep tms
		kill -9 
	
	六: 启动
	nohup java -jar -Dspring.profiles.active=beta -Dspring.config.location=application.properties tms.jar >tms.log &

下面是自己部署线上之前测试
在这里插入图片描述

其中校验了是否是图片,这个是两个项目中都用的此接口

package com.macro.mall.controller;

import com.macro.mall.dto.CommonResult;
import com.macro.mall.util.JwtTokenUtil;
import org.apache.commons.lang.time.DateFormatUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * @Desc 文件上传接口
 * @Date 2018/10/30 12:20
 * @Author cui_yl
 */
@RestController
@RequestMapping(value = "/file/***")
public class FileUploadController {
    private final static Logger logger = LoggerFactory.getLogger(FileUploadController.class);

    @Value(value = "${image.upload.host}")
    private String imageUploadHost;

    @Value(value = "${image.upload.path}")
    private String imageUploadPath;

    @Value(value = "${spring.profiles.active}")
    private String springProfilesActive;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Value("${jwt.tokenHead}")
    private String tokenHead;

    /**
     * @Desc 上传文件
     * @Date 2018/10/27 17:40
     * @Param []
     */
    @PostMapping("/upload-picture")
    public Object singleFileUpload(@RequestParam("file") MultipartFile file) {
        try {
            FileInputStream fileInputStream = (FileInputStream)file.getInputStream();
            String originalFilename = file.getOriginalFilename();
            if ((!originalFilename.toLowerCase().endsWith(".png") && !originalFilename.toLowerCase().endsWith(".jpg"))){
                return new CommonResult().validateFailed("请上传JPG/PNG格式图片");
            }

            String picType = getPicType(fileInputStream);
            if (!TYPE_JPG.equals(picType) && !TYPE_PNG.equals(picType)){
                return new CommonResult().validateFailed("请上传JPG/PNG格式图片");
            }

            File dir = new File(imageUploadPath);
            if(!dir.exists()) {
                dir.mkdir();
            }

            if (file.isEmpty()) {
                throw new RuntimeException("请选择一个文件上传!");
            }

            byte[] bytes = file.getBytes();
            String filename = DateFormatUtils.format(System.currentTimeMillis(), "yyyyMMdd")+"-"+UUID.randomUUID().toString()+"."+picType;
            Path path = Paths.get(imageUploadPath, filename);
            Files.write(path, bytes);
            String url=imageUploadHost+filename;
            /**
             *
             *  BufferedImage image = ImageIO.read(connection.getInputStream());
             *  int srcWidth = image .getWidth();      // 源图宽度
             *  int srcHeight = image .getHeight();    // 源图高度
             */

            BufferedImage image = ImageIO.read(file.getInputStream());
            int srcWidth = image .getWidth();      // 源图宽度
            int srcHeight = image .getHeight();    // 源图高度
            String size = String.valueOf(srcWidth)+"*"+String.valueOf(srcHeight);
            Map<String,Object> map = new HashMap<>();
            map.put("fileName",originalFilename);
            map.put("url",url);
            map.put("size",size);
            return new CommonResult().success( map);
        } catch (Exception e) {
            logger.error("上传文件失败"+e.getMessage(), e);
            return new CommonResult().failed("上传文件失败"+e.getMessage());
        }

    }

    private static final String TYPE_JPG = "jpg";
    private static final String TYPE_GIF = "gif";
    private static final String TYPE_PNG = "png";
    private static final String TYPE_BMP = "bmp";
    private static final String TYPE_UNKNOWN = "unknown";


    /**
     * 根据文件流判断图片类型
     * @param fis
     * @return jpg/png/gif/bmp
     */
    public static String getPicType(FileInputStream fis) throws Exception{
        byte[] b = new byte[4];//读取文件的前几个字节来判断图片格式
        try {
            fis.read(b, 0, b.length);
            String type = bytesToHexString(b).toUpperCase();
            if (type.contains("FFD8FF")) {
                return TYPE_JPG;
            } else if (type.contains("89504E47")) {
                return TYPE_PNG;
            } else if (type.contains("47494638")) {
                return TYPE_GIF;
            } else if (type.contains("424D")) {
                return TYPE_BMP;
            }else{
                return TYPE_UNKNOWN;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            if(fis != null){
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    /**
     * byte数组转换成16进制字符串
     * @param src
     * @return
     */
    public static String bytesToHexString(byte[] src) throws Exception{
        StringBuilder stringBuilder = new StringBuilder();
        if (src == null || src.length <= 0) {
            return null;
        }
        for (int i = 0; i < src.length; i++) {
            int v = src[i] & 0xFF;
            String hv = Integer.toHexString(v);
            if (hv.length() < 2) {
                stringBuilder.append(0);
            }
            stringBuilder.append(hv);
        }
        return stringBuilder.toString();
    }
}

下面这个是同事给的工具类, 感觉也很好

package com.macro.mall.util;

import java.io.File;
import java.io.FileOutputStream;
import java.util.UUID;

import org.apache.commons.lang.time.DateFormatUtils;

public class FileUtil {
    public static File uploadFile(byte[] file, String filePath, String fileName) {
        filePath = filePath+File.separator+ DateFormatUtils.format(System.currentTimeMillis(), "yyyyMM");
        File targetFile = new File(filePath);
        String suffix="";
        if(fileName.lastIndexOf(".")>0){
            suffix = fileName.substring(fileName.lastIndexOf("."));
        }
        if(!targetFile.exists()){    
            targetFile.mkdirs();    
        }       
        targetFile = new File(filePath+File.separator+UUID.randomUUID().toString()+suffix);
        try(FileOutputStream out = new FileOutputStream(targetFile)){
            out.write(file);
            out.flush();
            return targetFile;
        } catch (Exception e) {
        }finally {
            
        }
        
        return null;
    }

    public static String getSuffix(String fileName){
        if(fileName.lastIndexOf(".")>0){
            return fileName.substring(fileName.lastIndexOf("."));
        }else{
            return "";
        }
        
    }
    
    public static boolean delAllFile(String path) {  
        boolean flag = false;  
        File file = new File(path);  
        if (!file.exists()) {  
          return flag;  
        }  
        if (!file.isDirectory()) {  
          return flag;  
        }  
        String[] tempList = file.list();  
        File temp = null;  
        for (int i = 0; i < tempList.length; i++) {  
           if (path.endsWith(File.separator)) {  
              temp = new File(path + tempList[i]);  
           } else {  
               temp = new File(path + File.separator + tempList[i]);  
           }  
           if (temp.isFile()) {  
              temp.deleteOnExit();  
           }  
           if (temp.isDirectory()) {  
              delAllFile(path + "/" + tempList[i]);//先删除文件夹里面的文件  
              delFolder(path + "/" + tempList[i]);//再删除空文件夹  
              flag = true;  
           }  
        }  
        return flag;  
   }
    
    public static boolean delFolder(String folderPath) {  
        try {  
           delAllFile(folderPath); //删除完里面所有内容  
           String filePath = folderPath;  
           filePath = filePath.toString();  
           File myFilePath = new File(filePath);
           myFilePath.deleteOnExit();
           return true;
        } catch (Exception e) {  
//          logger.error("文件夹删除失败");   
          return false;
        }  
   }
}

下面是上传文件

  /**
    * @Desc 上传模板
    * @Date 2018/11/22 19:42
    * @Param [multipartRequest]
    */
   @PostMapping("/templatezip")
   public ResponseBean create(@RequestParam("file") MultipartFile file, @RequestHeader("Authorization") String authorization) {
       try {
           if (null == file){
               return new ResponseBean(400, "缺少文件");
           }
           int userId = JWTUtil.getUserId(authorization);
           long size = (file.getSize())/(1024*1024);
           if (size>=20){
               return new ResponseBean(400, "请以上传20M以内的压缩包");
           }
           String originalFilename = file.getOriginalFilename();
           if (!originalFilename.endsWith(".zip")){
               return new ResponseBean(400, "请以上传zip格式的压缩包");
           }

           File dir = new File(UPLOADED_FOLDER);
           if(!dir.exists()) {dir.mkdir();}
           byte[] bytes = file.getBytes();
           String filenameUUID = UUID.randomUUID().toString().replace("-", "")+".zip";
           if (StringUtils.isEmpty(filenameUUID)){
               throw new RuntimeException("获得模板UUID名称 error");
           }

           Path path = Paths.get(UPLOADED_FOLDER, filenameUUID);
           Files.write(path, bytes);//保存模板文件
           String uuidFilePath = path.toString();

           HashMap<String, String> map = new HashMap<>();
           map.put("originalFilename", originalFilename);
           map.put("uuidFilePath", uuidFilePath);
           return new ResponseBean(200, "上传成功", map);//返回模板绝对文件路径

       } catch (Exception e) {
           logger.warn("保存模板信息失败", e);
           return new ResponseBean("保存失败", 500);
       }
   }
  • 批量上传,但是代码中在返回批量上传后的图片路径时,由于业务只返回了第一个
package com.macro.mall.controller;


import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.macro.mall.dto.CommonResult;
import com.macro.mall.util.JwtTokenUtil;

import io.swagger.annotations.Api;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.stereotype.Controller;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;

/**
 * @Desc 文件上传接口
 * @Date 2018/10/30 12:20
 * @Author cui_yl
 */
@Api(tags = "FileUploadController",description = "文件上传")
@Controller
@RequestMapping(value = "/file")
public class FileUploadController {
    private final static Logger logger = LoggerFactory.getLogger(FileUploadController.class);

    @Value(value = "${image.upload.host}")
    private String imageUploadHost;

    @Value(value = "${image.upload.path}")
    private String imageUploadPath;

    @Value(value = "${spring.profiles.active}")
    private String springProfilesActive;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Value("${jwt.tokenHead}")
    private String tokenHead;

    /**
     * @Desc 上传文件
     * @Date 2018/10/27 17:40
     * @Param []
     */
    @PostMapping("/upload-picture")
    @ResponseBody
    public Object singleFileUpload(@RequestParam(value = "file") MultipartFile files[]) {
        try {
            if (null == files || files.length < 1) {
                throw new RuntimeException("请选择一个文件上传!");
            }
            File dir = new File(imageUploadPath);
            if(!dir.exists()) {
                dir.mkdirs();
            }
            List<Map> list = new ArrayList<>();
            BufferedOutputStream bw = null;
            try {
                for (MultipartFile file : files) {
                    String originalFilename = file.getOriginalFilename();
                    //判断是否有文件且是否为图片文件
                    if(originalFilename!=null && !"".equalsIgnoreCase(originalFilename.trim()) && isImageFile(originalFilename)) {
                        String fileName = DateFormatUtils.format(System.currentTimeMillis(), "yyyyMMdd")+"-"+UUID.randomUUID().toString()+ getFileType(originalFilename);
                        //创建输出文件对象
                        File outFile = new File(imageUploadPath + "/" +fileName);
                        //拷贝文件到输出文件对象
                        FileUtils.copyInputStreamToFile(file.getInputStream(), outFile);
                        String url=imageUploadHost+fileName;
                        /**
                         *
                         *  BufferedImage image = ImageIO.read(connection.getInputStream());
                         *  int srcWidth = image .getWidth();      // 源图宽度
                         *  int srcHeight = image .getHeight();    // 源图高度
                         */
                        BufferedImage image = ImageIO.read(file.getInputStream());
                        int srcWidth = image .getWidth();      // 源图宽度
                        int srcHeight = image .getHeight();    // 源图高度
                        String size = String.valueOf(srcWidth)+"*"+String.valueOf(srcHeight);
                        Map<String,Object> map = new HashMap<>();
                        map.put("fileName", originalFilename);
                        map.put("url", url);
                        map.put("size", size);
                        list.add(map);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    if (bw != null) {
                        bw.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return new CommonResult().success(list.get(0));
        } catch (Exception e) {
            logger.error("上传文件失败"+e.getMessage(), e);
            return new CommonResult().failed("上传文件失败"+e.getMessage());
        }
    }

    private static final String TYPE_JPG = "jpg";
    private static final String TYPE_GIF = "gif";
    private static final String TYPE_PNG = "png";
    private static final String TYPE_BMP = "bmp";
    private static final String TYPE_UNKNOWN = "unknown";

    private Boolean isImageFile(String fileName) {
        String[] img_type = new String[]{".jpg", ".jpeg", ".png", ".gif", ".bmp"};
        if (fileName == null) {
            return false;
        }
        fileName = fileName.toLowerCase();
        for (String type : img_type) {
            if (fileName.endsWith(type)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 获取文件后缀名
     *
     * @param fileName
     * @return
     */
    private String getFileType(String fileName) {
        if (fileName != null && fileName.indexOf(".") >= 0) {
            return fileName.substring(fileName.lastIndexOf("."), fileName.length());
        }
        return "";
    }

    /**
     * 根据文件流判断图片类型
     * @param fis
     * @return jpg/png/gif/bmp
     */
    public static String getPicType(FileInputStream fis) throws Exception{
        byte[] b = new byte[4];//读取文件的前几个字节来判断图片格式
        try {
            fis.read(b, 0, b.length);
            String type = bytesToHexString(b).toUpperCase();
            if (type.contains("FFD8FF")) {
                return TYPE_JPG;
            } else if (type.contains("89504E47")) {
                return TYPE_PNG;
            } else if (type.contains("47494638")) {
                return TYPE_GIF;
            } else if (type.contains("424D")) {
                return TYPE_BMP;
            }else{
                return TYPE_UNKNOWN;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            if(fis != null){
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }


    /**
     * byte数组转换成16进制字符串
     * @param src
     * @return
     */
    public static String bytesToHexString(byte[] src) throws Exception{
        StringBuilder stringBuilder = new StringBuilder();
        if (src == null || src.length <= 0) {
            return null;
        }
        for (int i = 0; i < src.length; i++) {
            int v = src[i] & 0xFF;
            String hv = Integer.toHexString(v);
            if (hv.length() < 2) {
                stringBuilder.append(0);
            }
            stringBuilder.append(hv);
        }
        return stringBuilder.toString();
    }
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值