V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
arseBurger
V2EX  ›  问与答

求助: springmvc 上传至 mongodb 后下载文件无法打开

  •  
  •   arseBurger · 2019-02-01 10:27:48 +08:00 · 1735 次点击
    这是一个创建于 2121 天前的主题,其中的信息可能已经有所发展或是发生改变。
    RT 球球大佬们帮忙看看是哪里出了问题
    ----上传


    /**
    *
    *接受前端上传的文件并存储至 MongoDB
    * @param file 前端上传的文件
    * @return 处理结果信息
    */
    @CrossOrigin
    @ResponseBody
    @RequestMapping(value = "/upload", method = RequestMethod.POST)
    public ReturnInfo fileUpload(@RequestParam MultipartFile file) throws Exception {
    ReturnInfo<Map> info = new ReturnInfo<>();
    if (!file.isEmpty()) {
    BufferedInputStream inputStream = new BufferedInputStream(file.getInputStream());
    String fileId = fileService.fileUpload(inputStream);
    info.setCode(ReturnInfo.OK);
    info.setMessage("上传成功!");
    Map<String, String> resultMap = new HashMap<>();
    resultMap.put("fileId", fileId);
    info.setData(resultMap);
    return info;
    } else {
    info.setMessage("文件不能为空");
    info.setCode(ReturnInfo.ERROR);
    return info;
    }

    }

    /**
    * 文件上传 service
    *
    * @param fileInput 文件输入流
    * @return mongodb 对应文件 id
    */
    @Override
    public String fileUpload(InputStream fileInput) throws RestServiceException {
    String fileType = FileUtil.getFileType(fileInput);
    System.out.println(fileType);
    //文件类型判断
    if (!FileUtil.ENABLE_TYPES.contains(fileType)) {
    throw new RestServiceException("不支持的文件类型!");
    }
    GridFSFile uploadFile = gridFsTemplate.store(fileInput, StringUtil.getUUID(), fileType);
    return uploadFile.getId().toString();
    }

    ----下载





    /**下载请求
    * 下载文件
    *
    * @param fileId 文件 ID
    * @return
    */
    @CrossOrigin
    @RequestMapping(value = "/download2/{fileId}", method = RequestMethod.GET)
    @ResponseBody
    public ResponseEntity<InputStreamResource> fileDownload2(@PathVariable String fileId) throws Exception {
    //从 MongoDB 获取文件
    GridFSDBFile file = fileService.getFileById(fileId);
    String fileType = file.getContentType();
    //设置文件 ContentType
    MediaType mediaType = FileUtil.getEnableStr(fileType);
    InputStreamResource resource = new InputStreamResource(file.getInputStream());
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(mediaType);
    headers.setContentDispositionFormData("attachment",file.getFilename()+"."+fileType);
    //返回前端
    return new ResponseEntity<>(resource, headers, HttpStatus.OK);
    }

    /**
    *下载 service
    */
    @Override
    public GridFSDBFile getFileById(String fileId) throws RestServiceException {
    GridFSDBFile file = gridFsTemplate.findOne(Query.query(Criteria.where("_id").is(fileId)));
    if (file == null) {
    throw new RestServiceException("找不到相关文件!请检查 fileId");
    }
    return file;
    }
    10 条回复    2019-02-01 16:12:31 +08:00
    arseBurger
        1
    arseBurger  
    OP
       2019-02-01 11:10:10 +08:00
    在吗? 看看题 : (
    arseBurger
        2
    arseBurger  
    OP
       2019-02-01 11:23:34 +08:00
    99 可怜的新手
    gz911122
        3
    gz911122  
       2019-02-01 12:12:59 +08:00
    不是 我就想问问文件存 MongoDB 是什么操作
    这玩意不应该都是存静态资源服务器,cdn 啥的吗
    undeflife
        4
    undeflife  
       2019-02-01 12:26:14 +08:00
    @gz911122 存的是 mongodb 的 GridFS
    undeflife
        5
    undeflife  
       2019-02-01 12:30:36 +08:00
    打不开是什么效果?没有后缀? 还是内容有问题?
    String fileType = file.getContentType();这里的 fileType 是对的吗
    下载后的文件 hash 对吗?
    arseBurger
        6
    arseBurger  
    OP
       2019-02-01 13:28:34 +08:00
    @undeflife 感谢回复,fileType 是存到 GridFs 里的文件后缀名,如下记录:
    {
    "filename" : "3514bd478bbe476b8628daa5d2f03156",
    "aliases" : null,
    "chunkSize" : NumberLong(261120),
    "uploadDate" : ISODate("2019-01-31T05:20:51.364+0000"),
    "length" : NumberLong(6035),
    "_id" : ObjectId("5c5285b32293366f443d190d"),
    "contentType" : "txt",
    "md5" : "06d90ff5b133aceecd080fdcff475b1b"
    }

    我试了一下下载 FileSystem 上的文件同样有这个问题,应该可以排除 mongodb 存储的问题了
    arseBurger
        7
    arseBurger  
    OP
       2019-02-01 13:45:12 +08:00
    @undeflife ....修改一下...FileSystem 上的文件下载只有 Txt 能正常打开,其他的还是不行 :(
    这段是判断文件类型的方法:
    /**
    * 根据制定文件的文件头判断其文件类型
    *
    * @param
    * @return
    */
    public static String getFileType(InputStream inputStream) {
    String res = null;
    try {
    byte[] b = new byte[10];
    inputStream.read(b, 0, b.length);
    String fileCode = bytesToHexString(b);

    System.out.println(fileCode);

    //这种方法在字典的头代码不够位数的时候可以用但是速度相对慢一点
    Iterator<String> keyIter = FILE_TYPE_MAP.keySet().iterator();
    while (keyIter.hasNext()) {
    String key = keyIter.next();
    if (key.toLowerCase().startsWith(fileCode.toLowerCase()) || fileCode.toLowerCase().startsWith(key.toLowerCase())) {
    res = FILE_TYPE_MAP.get(key);
    break;
    }
    }
    } catch (IOException e) {
    e.printStackTrace();
    }
    return res;
    }

    这段是匹配 MediaType 的方法:
    /**
    * @param fileType
    * @return
    */
    public static MediaType getEnableStr(String fileType) {
    if (IMAGE_TYPES.contains(fileType)) {
    return MediaType.valueOf("image/" + fileType);
    } else if (PDF_TYPES.contains(fileType)) {
    return MediaType.APPLICATION_PDF;
    } else if (TXT_TYPES.contains(fileType)) {
    return MediaType.TEXT_PLAIN;
    } else {
    return MediaType.APPLICATION_OCTET_STREAM;
    }
    }
    undeflife
        8
    undeflife  
       2019-02-01 13:55:42 +08:00
    @arseBurger 不是 你一直没表达清楚的是 "无法打开" 是浏览器直接打开 还是下载到本地后不能打开? 不能打开又是什么效果?
    arseBurger
        9
    arseBurger  
    OP
       2019-02-01 14:42:57 +08:00
    @undeflife 嗯嗯,不好意思,我没表述清楚,是下载到本地后无法打开,照片类型的提示无法打开此文件,doc 文档提示发现有无法读取的内容,mp4 文件提示此文件无法播放。这可能是因为文件类型不受支持、文件扩展名不正确或文件已损坏。
    undeflife
        10
    undeflife  
       2019-02-01 16:12:31 +08:00
    @arseBurger 你的代码我没细看 粗看没太大问题 我觉得你比对文件在各个装下的 md5 是不是都一致
    另外我记得 gridfs 的封装里 contentType 这个字段本身就是 MIME type 感觉你这部分处理有点不对 甚至直接作为附件的文件后缀了.
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   4970 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 36ms · UTC 09:40 · PVG 17:40 · LAX 01:40 · JFK 04:40
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.