当前位置: 首页 > 知识库问答 >
问题:

Spring-如何将大型多部分文件上传到数据库,而不存储在本地文件系统中[重复]

公冶子琪
2023-03-14

Spring boot的默认MultiPartResolver接口通过将多部分文件存储在本地文件系统上来处理多部分文件的上传。在输入控制器方法之前,整个多部分文件必须完成上传到服务器。

我们将所有上传的文件直接存储到数据库中,我们的服务器只有很小的磁盘配额,因此如果上传了一个大文件,我们会看到< code > ioexeception-磁盘配额超出。

在Spring的MultiPartResolver将文件存储在本地文件系统之前,有没有一种方法可以直接从客户机的传入请求中获取流,以便我们可以直接将流传输到我们的db?

共有2个答案

百里君博
2023-03-14

事实上,这不是一件小事。如果您想将流从客户端写入数据库,则必须手动处理请求。有一些库可以使此任务更简单。其中之一是“Apache Commons文件上传”。下面是一个非常简单的示例,您如何处理此库传入的<code>多部分/表单数据

@Controller
public class Controller{

    @RequestMapping("/upload")
    public String upload(HttpServletRequest request){
        
        String boundary = extractBoundary(request);

        try {
            MultipartStream multipartStream = new MultipartStream(request.getInputStream(), 
                boundary.getBytes(), 1024, null);
            boolean nextPart = multipartStream.skipPreamble();
            while(nextPart) {
                String header = multipartStream.readHeaders();

                if(header.contains("filename")){
                    //if input is file
                    OutputStream output = createDbOutputStream();
                    multipartStream.readBodyData(output);
                    output.flush();
                    output.close();
                } else {
                    //if input is not file (text, checkbox etc)
                    ByteArrayOutputStream output = new ByteArrayOutputStream();
                    multipartStream.readBodyData(output);
                    String value = output.toString("utf-8");
                    //... do something with extracted value
                }
                nextPart = multipartStream.readBoundary();
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }    
    }

    private String extractBoundary(HttpServletRequest request) {
        String boundaryHeader = "boundary=";
        int i = request.getContentType().indexOf(boundaryHeader)+
            boundaryHeader.length();
        return request.getContentType().substring(i);
    }    
}

文件字段的标题如下所示:

Content-Disposition: form-data; name="fieldName"; filename="fileName.jpg"
Content-Type: image/jpeg

简单字段的标题将如下所示:

Content-Disposition: form-data; name="fieldName";

请注意,此片段只是向您展示方向的简化示例。没有一些细节,例如:从标头中提取字段名、创建数据库输出流等。您可以自己实现所有这些东西。您可以在RFC1867中找到多部分请求的字段标头示例。有关multipart/form-dataRFC2388的信息。

侯沈义
2023-03-14

您可以直接使用 apache,如此处所述 https://commons.apache.org/proper/commons-fileupload/streaming.html。

@Controller
public class UploadController {

    @RequestMapping("/upload")
    public String upload(HttpServletRequest request) throws IOException, FileUploadException {

        ServletFileUpload upload = new ServletFileUpload();

        FileItemIterator iterator = upload.getItemIterator(request);
        while (iterator.hasNext()) {
            FileItemStream item = iterator.next();

            if (!item.isFormField()) {
                InputStream inputStream = item.openStream();
                //...
            }
        }
    }
}

确保禁用Spring多部分解析机制

application.yml:

spring:
   http:
      multipart:
         enabled: false
 类似资料:
  • 问题内容: 我的一位客户要求为成千上万种不同格式(例如pdf,doc,docx等)的文档提供文档管理系统。我的问题是在数据库或文件系统中存储此文件的最佳方法是什么?两种方法之间如何轻松保护文档? 快速检索文件是关键要求。 我正在使用mysql如果有帮助 问候。 问题答案: 您可能希望将其直接存储到文件系统中。 使用文件系统时,请注意: 机密性: 将文档放在Apache文档根目录之外。然后,您的PH

  • Gradle如何在本地文件系统上存储下载的jar文件?Maven将它们存储在下的目录中,但Gradle将它们存储在哪里?我检查了那里的文件夹,但只看到编译过的脚本。

  • 我已经在Ubuntu 14.04上安装了hadoop。每当我将文件从本地文件系统复制到HDFS时,我都会出现以下错误。 我使用这个命令: 我遇到的错误是: 我是Linux环境的新手。我不明白哪个文件不存在。

  • 问题内容: 我有两个网站,一个是TLS,一个不是,这两个都是针对同一客户端的,但是我需要这些网站彼此(并且只能彼此)共享 用户 , 订单 , 帐户 等的通用数据。 通常可以使用数据完成此操作,但是我显然不能在其他站点上使用它们,而且我发现我可以将会话数据存储在数据库(MySQL)中,而不是文件系统中。 我已经四处搜寻,发现此有用的指南以及此较旧但 有用的指南。我还发现了该指南,该指南具有最新的My

  • 如何将文件从HDFS复制到本地文件系统。文件下没有文件的物理位置,甚至没有目录。我如何将它们移到本地进行进一步的验证。我通过winscp进行了尝试。

  • 我是Spring初学者,我正在使用Spring mvc 4 hibernate和mysql创建一个项目。在这个项目中,用户可以提交一个带有他们的个人资料图片的表单“意味着,我需要连同图像文件一起提交数据”。我可以将文件作为blob存储在数据库中,但这不是一个好的做法,因此我试图在数据库中仅存储文件的名称。 到目前为止,我所做的工作是:在我的xml配置中使用multipartviewresolver