php如何将上传的二进制流文件转化为multipartfile

php如何将上传的二进制流文件转化为multipartfile,第1张

在PHP中,可以使用$_FILES超全局变量来处理上传文件,该变量是一个关联数组,其中包含有关上传文件的信息,例如文件名、文件类型、文件大小等。可以使用move_uploaded_file()函数将上传的文件保存到服务器的指定目录中。

如果要将上传的二进制流文件转换为MultipartFile,需要使用第三方库来实现。例如,可以使用GuzzleHttp库将二进制数据流转换为StreamInterface对象,然后将其传递给UploadedFile类的构造函数。

下面是一个示例代码,演示如何将上传的二进制流文件转换为MultipartFile:

use GuzzleHttp\Psr7\Stream

use Symfony\Component\HttpFoundation\File\UploadedFile

// 获取上传的文件流

$fileContent = file_get_contents($_FILES['file']['tmp_name'])

// 将二进制流转换为 StreamInterface 对象

$stream = new Stream(fopen('php://memory','r+'))

$stream->write($fileContent)

// 创建 UploadedFile 对象

$file = new UploadedFile(

$stream,

$_FILES['file']['name'],

$_FILES['file']['type'],

$_FILES['file']['size'],

UPLOAD_ERR_OK,

true // 是否删除临时文件

)

// 现在 $file 是一个 MultipartFile 对象,可以将其传递给需要的函数进行处理

注意,上述示例中使用了GuzzleHttp和Symfony两个第三方库,需要事先安装和引入这些库才能正常运行代码。

MultipartFile提供了以下方法来获取上传文件的信息:

getOriginalFilename,获取上传的文件名字;

getBytes,获取上传文件内容,转为字节数组;

getInputStream,获取一个InputStream;

isEmpty,文件上传内容为空,或者根本就没有文件上传;

getSize,文件上传的大小。

transferTo(File dest),保存文件到目标文件系统;

同时上传多个文件,则使用MultipartFile数组类来接受多个文件上传:

//多文件上传@RequestMapping(value = "/batch/upload", method = RequestMethod.POST)

    @ResponseBody    public String handleFileUpload(HttpServletRequest request){

        List<MultipartFile>files = ((MultipartHttpServletRequest) request)

                .getFiles("file")

        MultipartFile file = null

        BufferedOutputStream stream = null

        for (int i = 0i <files.size()++i) {

            file = files.get(i)

            if (!file.isEmpty()) {

                try {

                    byte[] bytes = file.getBytes()

                    stream = new BufferedOutputStream(new FileOutputStream(

                            new File(file.getOriginalFilename())))

                    stream.write(bytes)

                    stream.close()

                } catch (Exception e) {

                    stream = null

                    return "You failed to upload " + i + " =>"                            + e.getMessage()

                }

            } else {

                return "You failed to upload " + i

                        + " because the file was empty."

            }

        }

        return "upload successful"

    }

可以通过配置application.properties对SpringBoot上传的文件进行限定默认为如下配置:

spring.servlet.multipart.enabled=true

spring.servlet.multipart.file-size-threshold=0

spring.servlet.multipart.location=

spring.servlet.multipart.max-file-size=1MB

spring.servlet.multipart.max-request-size=10MB

spring.servlet.multipart.resolve-lazily=false

enabled默认为true,既允许附件上传。

file-size-threshold限定了当上传文件超过一定长度时,就先写到临时文件里。有助于上传文件不占用过多的内存,单位是MB或KB,默认0,既不限定阈值。

location指的是临时文件的存放目录,如果不设定,则web服务器提供一个临时目录。

max-file-size属性指定了单个文件的最大长度,默认1MB,max-request-size属性说明单次HTTP请求上传的最大长度,默认10MB.

resolve-lazily表示当文件和参数被访问的时候再被解析成文件。

时间:2020.12.4

异常:java.io.FileNotFoundException: /home/jdp/apache-tomcat-8.5.54-8-group/apache-tomcat-8.5.54-80 /work/Catalina/localhost/ROOT/upload_cda0de04_fa66_4589_8170_5cb0cb7f8152_00000005.tmp

初步判断:文件上传路径问题,但是项目路径中并未配置这个路径,后面了解到 /work 是tomcat 编译文件的临时路径,联想到 /work 之后的文件可能是上传的临时文件路径,而前面的路径是tomcat的绝对路径

探索1:项目配置的文件路径为/home/temp, 可能是因为tomcat的临时文件路径和我们上传的临时文件路径不匹配导致的

尝试1:设置tomcat 临时文件路径 在 application.properites 中配置 增加配置 server.tomcat.basedir=/home/temp

结果1:未解决,报错不变

探索2:查阅资料得知 MultipartFile.transferTo(targetFile) 方法是面向绝对路径的,如果入参是一个相对路径,则会在路径之前加上 一个系统绝对路径(比较符合我们的情况)

尝试2:根据文章所述:增加配置类 指定临时文件的路径

@Configuration

public class FileUploadConfig {

    @Value("${file.temp.root}")

    private String FILE_TEMP_ROOT

    /**

    * 文件上传配置

    *

    * @return MultipartConfigElement

    */

    @Bean

    public MultipartConfigElement multipartConfigElement(

            @Value("${multipart.maxFileSize}") String maxFileSize,

            @Value("${multipart.maxRequestSize}") String maxRequestSize) {

        MultipartConfigFactory factory = new MultipartConfigFactory()

        // 单个文件最大

        factory.setMaxFileSize(maxFileSize)

        // 设置总上传数据总大小

        factory.setMaxRequestSize(maxRequestSize)

        //上传临时路径

        File file = new File(FILE_TEMP_ROOT)

        if (!file.exists()) {

            file.mkdirs()

        }

        factory.setLocation(FILE_TEMP_ROOT)

        return factory.createMultipartConfig()

    }

}

结果2:报错发生变化,变成了我们的指定的路径加上 临时文件名,但是依旧未能解决问题

java.io.FileNotFoundException: /home/temp/upload_a8eb4246_470f_4f73_81af_891f1ad6651b_00000002.tmp

转换思路:既然是transferTo()方法的问题,换一个方法

探索3:更换transferTo()方法,使用 FileUtils.copyInputStreamToFile(sourceFile.getInputStream(), targetFile)方法

尝试3:寻找方法中包涵的transfTo()方法,替换成FileUtils.copyInputStreamToFile(sourceFile.getInputStream(), targetFile)

结果3:问题解决

总结:transferTo()在windows 系统上并没有这个问题,在Linux上出现了这个问题,网上的资料各有说法,目前未找到真正的原因。为了避免这个问题,统一使用FileUtils.copyInputStreamToFile(sourceFile.getInputStream(), targetFile)方法来复制文件。


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/tougao/12031370.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-20
下一篇2023-05-20

发表评论

登录后才能评论

评论列表(0条)

    保存