【问题标题】:Java Convert MultipartFile to File for large filesJava将MultipartFile转换为大文件的文件
【发布时间】:2018-10-05 10:19:11
【问题描述】:

我正在使用以下方法将 MultipartFile 转换为文件:

public File convert(MultipartFile file) throws IOException {
        File convFile = new File(file.getOriginalFilename());
        convFile.createNewFile();
        FileOutputStream fos = new FileOutputStream(convFile);
        fos.write(file.getBytes());
        fos.close();
        return convFile;
}

Wich 工作很好,但对于大文件我得到了这个例外:

java.lang.OutOfMemoryError: Java heap space

我添加了更多堆,但仍然有错误。

那么有没有一种编程方式来解决这个问题,可能在转换时将多部分文件分成更小的块,但我不知道如何编码。

任何帮助或建议将不胜感激。

【问题讨论】:

  • file.getInputStream() 将返回该流,对您有帮助吗?
  • MulipartFile 应该有一个 toFile(file) 方法。
  • new File(file.getOriginalFilename())。嗯,如果两个同时请求同时上传“untitled.pdf”会发生什么?各种各样的坏事,我想。另外,恶意用户将有一个现场日。我个人很想尝试“C:\Win32\whatever”或“~/bash.rc”作为示例名称(不要这样做!永远不要相信用户提交的内容)
  • @GPI 实际上,我们永远不会有 2 个同名的文件,因为我在文件末尾附加了时间,如下所示:“untitled-09-10-2018-hh-mm-ss- ms.pdf"
  • 好的,很高兴知道...但是您仍然有用户生成的前缀路径?那可能很危险。如果用户文件名包含 "/" 或 ":" 或 "\" 怎么办?我会将用户生成的名称视为元数据(如果不需要,也可以将其完全删除),并生成一个唯一的、FS 安全的名称(例如 Files.createXXXFile 方法系列)。

标签: java spring multipart


【解决方案1】:

MultipartFile 是否属于 Spring 的包 org.springframework.web.multipart?如果是这样,你可以这样做

  public File convert(MultipartFile file) throws IOException {
    File convFile = new File(file.getOriginalFilename());
    convFile.createNewFile();
      try(InputStream is = file.getInputStream()) {
        Files.copy(is, convFile.toPath()); 
      }
    return convFile;
  }

【讨论】:

  • 它显示此错误无法解析此行 Files.copy(...) 上的方法 'copy(java.io.InputStream, java.io.FileOutputStream)
  • 出现异常时不会关闭流。此处应使用 try-with-resources (FileOutputStream fos = new FileOutputStream(convFile))。
  • 我不知道你从哪里得到Files.copy(InputStream, OutputStream),但输入流可能也应该正确关闭(但这取决于库)。
  • @AbdenaceurLichiheb 这可能是一个错误,OP 的意思是来自 Apache Commons IO 的 IOUtils#copy 或 Guava 的 ByteStreams#copy
  • @AbdenaceurLichiheb Files.readAllBytes() 将所有字节读入内存并可能导致 OOME。您应该尝试从流中读取。
【解决方案2】:

下面的代码将帮助您将文件分成大块,然后您必须聚合

try
        {
            file = new File(filePath.toString());
            messageDigest = MessageDigest.getInstance("MD5");
            checksum = getFileCheckSum(messageDigest, file);
            fileInputStream = new FileInputStream(file);
            int fileSize = (int) file.length();
            fileChannel = fileInputStream.getChannel();
            int numberOfChunks = (int) Math.ceil(fileChannel.size() / (double) chunkSize);
            int totalpacket = numberOfChunks;
            int totalFileSize = fileSize;
            int read = 0;

            while (numberOfChunks > 0)
            {

                System.out.println("file is :" + file + "checksum is:" + checksum);
                fileSize -= read;

                if (numberOfChunks > 1)
                {
                    ByteBuffer bytebuffer = ByteBuffer.allocate(chunkSize);
                    read = fileChannel.read(bytebuffer);
                    bytebuffer.flip();
                    String content = new String();
                    if (bytebuffer.hasRemaining())
                    {
                        content = new String(bytebuffer.array(), Charset.forName("UTF-8"));

                    }


                    bytebuffer.clear();

                }
                else
                {

                    String chunkData = new String();
                    ByteBuffer byteBuffer = ByteBuffer.allocate(fileSize);
                    fileChannel.read(byteBuffer);
                    chunkData = new String(byteBuffer.array(), Charset.forName("UTF-8"));
                    byteBuffer.clear();
                }

                numberOfChunks--;
            }
        }
        catch (IOException e)
        {
            log.info(e);
        }
        catch (NoSuchAlgorithmException nsae)
        {
            log.info(nsae);
        }
        finally
        {
            try
            {
                fileInputStream.close();
                fileChannel.close();
            }
            catch (IOException ioe)
            {
                log.info(ioe);
            }

        }

【讨论】:

    【解决方案3】:

    使用 transferTo 怎么样:

    public File convert(MultipartFile file) throws IOException 
     {
      File convFile = new File(file.getOriginalFilename());
      file.transferTo(convFile);
      return convFile;
    }
    

    【讨论】:

    • 这个方法不保存我得到FileNotFoundException的文件
    • 对不起,您必须先添加一个创建语句。
    • create 语句是什么意思?
    • public File convert(MultipartFile file) throws IOException { File convFile = new File(file.getOriginalFilename()); convFile.createNewFile(); file.transferTo(convFile);返回转换文件; }
    • 我检查了 api 并且 createNewFile 没有帮助。看起来重点可能是您的环境 - 您是否使用 servlet 3.x api 运行?
    猜你喜欢
    • 1970-01-01
    • 2023-03-05
    • 2013-05-31
    • 1970-01-01
    • 2020-03-02
    • 2015-05-17
    • 2021-10-04
    • 2018-05-04
    • 1970-01-01
    相关资源
    最近更新 更多