• 【排坑】websoucket场景下文件无法上传到服务器的解决方案


    业务背景:几乎很多app都有文件交互的功能,诸如头像管理、材料上传等等。在我们的一次在线签约场景中,需要在websoucket场景下来实现文件上传功能。也算是前一篇文章《【JAVA、Tomcat、WebSocket】配置文件保存路径、实现前端直接访问本地文件路径,后端实时保存代码实现》所遇到问题的解决方案。

    一、问题描述及解决

    具体文件上传业务代码在如上标注的文章中,可见前端传入到接口的格式是String类型的Base64字符串,这里面有第一个坑就是以String接的话,会存在”/r/n“这些转义符,我们需要做一个replace即byte[] bytes = Base64.getDecoder().decode(base64.replace("\r\n",""));

    接下来在我们自己本地测试,使用整套流程都没有问题。然而代码放到了服务器上就无法将文件写入到服务器指定位置。
    这里面写入先后用到的是FileOutputStream、BufferedOutputStream,再找问题时找到一篇大概很有帮助的文章,同时也参考了很多方案都没有起效果。
    Java踩坑笔记 —— 关于OutPutStream流无法在Process应用场景写入失败解决方案

    于是,转变思路。我们平常封装好的通过File或者MultipartFile格式的工具类来接收前端传入的文件,一般工具类如下:

    public class FileUtil {
        public static String uploadFile(MultipartFile file) {
        	//获取文件上传路径
        	String path = "/tomcat/webapps/file";
    //    	String path = "D:\\file";
        	String originalFilename = file.getOriginalFilename();
            //获取文件后缀
            String substring = originalFilename.substring(originalFilename.lastIndexOf("."));
            File targetFile ;
            //拼接新文件名(时间戳+5位数随机数)
            String photoFileName=System.currentTimeMillis() + RandomUtil.getAllNum(5) + substring;
            try {
                File upload = new File(path);
                if(!upload.exists()) {
                	upload.mkdirs();
                }
                targetFile = new File(path, photoFileName);
            	//将上传的文件写到服务器上指定的目录。
                file.transferTo(targetFile);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return "/file/" + photoFileName;
        }
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    但是缺陷就是需要前端转换传输格式,虽然稳妥,但在原基础上工作量增加很多。又经过一阵子寻找,最终找到一个更好的方案,在原基础上同样吧String类型的Base64字符串转换成byte 用ByteArrayInputStream、FileOutputStream写入完成,并且返还图片地址、图片名称。

    public class ToImgUtil {
        private String base;
     
        public ToImgUtil() {
        }
     
        public ToImgUtil(String base) {
            this.base = base;
        }
     
        public String getBase() {
            return base;
        }
     
        public void setBase(String base) {
            this.base = base;
        }
     
        /**
         * 为文件重新命名,命名规则为当前系统时间毫秒数
         *
         * @return string
         */
        private static String getFileNameNew() {
            SimpleDateFormat fmt = new SimpleDateFormat("yyyyMMddHHmmssSSS");
            return fmt.format(new Date());
        }
        public static Map ToImg(String base){
            //获取年月日
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            //将年、月、日存入数组
            String[] time = sdf.format(new Date()).split("-");
            // 文件保存地址 默认地址为xxxx/年/月/日
    //        String destDir = "xxxx/"+time[0]+"/"+time[1]+"/"+time[2];;
            String destDir = "/tomcat/webapps/file";
            /* response.setHeader("Access-Control-Allow-Origin", "*");
             response.setHeader("Access-Control-Allow-Methods", "POST");*/
            base=base.replaceAll("data:image/png;base64,","");
            BASE64Decoder decoder =  new BASE64Decoder();
            byte[] imageByte = null;
            try{
                imageByte = decoder.decodeBuffer(base);
                for (int i = 0; i < imageByte.length; ++i) {
                    if (imageByte[i] < 0) {// 调整异常数据
                        imageByte[i] += 256;
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            if (imageByte.length>0) {
                try {
                    String filepath = destDir;
                    File destfile = new File( filepath);
                    if (!destfile.exists()) {
                        destfile.mkdirs();
                    }
                    //文件新名称
                    String fileNameNew = getFileNameNew() + ".png";
                    File f = new File(destfile.getAbsoluteFile() + File.separator + fileNameNew);
                    // 将字符串转换成二进制,用于显示图片
                    // 将上面生成的图片格式字符串 imgStr,还原成图片显示
                    InputStream in = new ByteArrayInputStream(imageByte);
                    FileOutputStream fos = new FileOutputStream(f);
                    // BufferedOutputStream bos = new BufferedOutputStream(fos);
                    byte[] buf = new byte[1024];
                    int length;
                    length = in.read(buf, 0, buf.length);
     
                    while (length != -1) {
                        fos.write(buf,0,length);
                        length = in.read(buf);
                    }
                    fos.flush();
                    fos.close();
                    in.close();
                    Map<String,String> map = new HashedMap<>();
                    map.put("destDir",destDir);
                    map.put("fileNameNew",fileNameNew);
                    return map;
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                }
            }
            return null;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88

    二、资料引申

    Socket通讯使用遇到(BufferedReader||Write)(Output||InputStream)(Object Input||Output Stream)的问题/阻塞/空

    Base64转MultipartFile

    Java将base64字符串转成MultipartFile类型

    Base64转MultipartFile工具类

    WebSocket

  • 相关阅读:
    【Ubuntu 装机】Ubuntu18.04 20.04 desktop 装机过程,装机软件
    二、演练领域驱动的设计过程
    冠达管理:“旺季”来临,煤炭板块走高,云煤能源、陕西黑猫涨停
    后端工程师之路(6)注解与反射
    DevOps(八)Jenkins的Maven和Git插件
    librtmp源码详解
    如何使用ArcGIS Pro生成等高线
    二叉树 | 递归遍历 | leecode刷题笔记
    vulnhub靶机raven2
    如何在OneFlow中新增算子
  • 原文地址:https://blog.csdn.net/qq_48424581/article/details/126958908