好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

MultipartFile中transferTo(File file)的路径问题及解决

transferTo(File file)的路径问题

今天看到layui的文件上传的控件,就尝试了一下。简单创建了一个SpringMVC项目。记得在配置文件中注入以下Bean。

<!-- 定义文件上传解析器 --> <bean id = "multipartResolver" class = "org.springframework.web.multipart测试数据mons.CommonsMultipartResolver" > <!-- 设定默认编码 --> <property name = "defaultEncoding" value = "UTF-8" ></property> <!-- 设定文件上传的最大值为5MB,5*1024*1024 --> <property name = "maxUploadSize" value = "5242880" ></property> <!-- 设定文件上传时写入内存的最大值,如果小于这个参数不会生成临时文件,默认为10240 --> <property name = "maxInMemorySize" value = "40960" ></property> <!-- 上传文件的临时路径 --> <property name = "uploadTempDir" value = "fileUpload/temp" ></property> <!-- 延迟文件解析 --> <property name = "resolveLazily" value = "true" /> </bean>

我很懒,这些属性都没有配置,就注册了Bean。

接下来是我出错的地方。先上Controller代码,前台通过Layui的文件上传模块上传文件。

@ResponseBody @RequestMapping ( "/upload" ) public Map upload ( HttpServletRequest request , MultipartFile file ){ HashMap < String , String > map = new HashMap (); if (! file . isEmpty ()) { try { // getOriginalFilename()是包含源文件后缀的全名 String filePath = "D:/upload/test/" + file . getOriginalFilename (); System . out . println ( filePath ); File saveDir = new File ( filePath ); if (! saveDir . getParentFile (). exists ()) saveDir . getParentFile (). mkdirs (); file . transferTo ( saveDir ); map . put ( "res" , "上传成功" ); return map ; } catch ( Exception e ) { e . printStackTrace (); } } map . put ( "res" , "上传失败" ); return map ; }

transferTo方法中传递的file如果是路径的话,那么它会将最后一层路径当做文件名,没有后缀的那种。此时重命名这个文件,更改成和上传文件一致的后缀那么就可以打开了。

比如我将

String filePath = "D:/upload/test/" + file . getOriginalFilename ();

改成

String filePath = "D:/upload/test" ;

运行之后打开文件发现这样的:

transferTo将我想作为文件夹的test当做文件名了。我加个后缀.jpg

和上传的文件一致。

最后个人理解为传入的File参数是应该包含文件而不是文件路径,transferTo()并不会将文件转存到文件夹下。

MultipartFile.transferTo( )遇见的问题记录

环境:

Springboot 2.0.4 JDK8

表单,enctype 和 input 的type=file 即可,例子使用单文件上传

<form enctype = "multipart/form-data" method = "POST" action = "/file/fileUpload" > 图片 <input type = "file" name = "file" /> <input type = "submit" value = "上传" /> </form>

1.文件上传接值的几种方式

#spring.servlet.multipart.location=D:/fileupload1

/** * 使用 httpServletRequest作为参数 * @param httpServletRequest * @return */ @PostMapping ( "/upload" ) @ResponseBody public Map < String , Object > upload ( HttpServletRequest httpServletRequest ){ boolean flag = false ; MultipartHttpServletRequest multipartHttpServletRequest = null ; //强制转换为MultipartHttpServletRequest接口对象 (它包含所有HttpServletRequest的方法) if ( httpServletRequest instanceof MultipartHttpServletRequest ){ multipartHttpServletRequest = ( MultipartHttpServletRequest ) httpServletRequest ; } else { return dealResultMap ( false , "上传失败" ); } //获取MultipartFile文件信息(注意参数为前端对应的参数名称) MultipartFile mf = multipartHttpServletRequest . getFile ( "file" ); //获取源文件名称 String fileName = mf . getOriginalFilename (); //存储路径可在配置文件中指定 File pfile = new File ( "D:/fileupload1/" ); if (! pfile . exists ()) { pfile . mkdirs (); } File file = new File ( pfile , fileName ); /* //指定好存储路径 File file = new File(fileName);*/ try { //保存文件 //使用此方法保存必须要绝对路径且文件夹必须已存在,否则报错 mf . transferTo ( file ); } catch ( IOException e ) { e . printStackTrace (); return dealResultMap ( false , "上传失败" ); } return dealResultMap ( true , "上传成功" ); } /** * 使用Spring MVC的multipartFile 类作为参数 * * @param multipartFile * @return */ @PostMapping ( "/upload/MultipartFile" ) @ResponseBody public Map < String , Object > uploadMultipartFile ( @RequestParam ( "file" ) MultipartFile multipartFile ){ String fileName = multipartFile . getOriginalFilename (); try { //获取文件字节数组 byte [] bytes = multipartFile . getBytes (); //文件存储路径(/fileupload1/ 这样会在根目录下创建问价夹) File pfile = new File ( "/fileupload1/" ); //判断文件夹是否存在 if (! pfile . exists ()){ //不存在时,创建文件夹 pfile . mkdirs (); } //创建文件 File file = new File ( pfile , fileName ); //写入指定文件夹 OutputStream out = new FileOutputStream ( file ); out . write ( bytes ); } catch ( IOException e ) { e . printStackTrace (); return dealResultMap ( false , "上传失败" ); } /*//如果配置文件指定目录,就可以直接这样写(不指定路径的,就需要自己填充保存路径) File file = new File(fileName); try { //使用此方法保存必须要绝对路径且文件夹必须已存在,否则报错 multipartFile.transferTo(file); } catch (IOException e) { e.printStackTrace(); return dealResultMap(false, "上传失败"); }*/ return dealResultMap ( true , "上传成功" ); } @PostMapping ( "/upload/part" ) @ResponseBody public Map < String , Object > uploadPart ( @RequestParam ( "file" ) Part part ){ System . out . println ( part . getSubmittedFileName ()); System . out . println ( part . getName ()); //输入流 InputStream inputStream = null ; try { inputStream = part . getInputStream (); } catch ( IOException e ) { e . printStackTrace (); return dealResultMap ( false , "上传失败" ); } //保存到临时文件 //1K的数据缓冲流 byte [] bytes = new byte [ 1024 ]; //读取到的数据长度 int len ; //输出的文件保存到本地文件 File pfile = new File ( "/fileupload1/" ); if (! pfile . exists ()) { pfile . mkdirs (); } File file = new File ( pfile , part . getSubmittedFileName ()); OutputStream out ; try { out = new FileOutputStream ( file ); //开始读取 while (( len = inputStream . read ( bytes )) != - 1 ){ out . write ( bytes , 0 , len ); } } catch ( FileNotFoundException e ) { e . printStackTrace (); return dealResultMap ( false , "上传失败" ); } catch ( IOException e ) { e . printStackTrace (); return dealResultMap ( false , "上传失败" ); } /*//配置文件配置的有默认上传路径 //获取提交文件的名字 String fileName = part.getSubmittedFileName(); try { //使用此方法保存必须要绝对路径且文件夹必须已存在,否则报错 part.write(fileName); } catch (IOException e) { e.printStackTrace(); return dealResultMap(false, "上传失败"); }*/ return dealResultMap ( true , "上传成功" ); }

注意:

MultipartFile.transferTo() 需要的事相对路径

file.transferTo 方法调用时,判断如果是相对路径,则使用temp目录,为父目录

一则,位置不对,二则没有父目录存在,因此产生上述错误。

//1.使用此方法保存必须指定盘符(在系统配置时要配绝对路径); // 也可以通过 File f = new File(new File(path).getAbsolutePath()+ "/" + fileName); 取得在服务器中的绝对路径 保存即可 // file.transferTo(f); //2.使用此方法保存可相对路径(/var/falcon/)也可绝对路径(D:/var/falcon/) byte [] bytes = file . getBytes (); OutputStream out = new FileOutputStream ( f ); out . write ( bytes );

2.关于上传文件的访问

(1).增加一个自定义的ResourceHandler把目录公布出去

// 写一个Java Config @Configuration public class webMvcConfig implements org . springframework . web . servlet . config . annotation . WebMvcConfigurer { // 定义在application.properties @Value ( "${file.upload.path}" ) private String path = "upload/" ; public void addResourceHandlers ( ResourceHandlerRegistry registry ) { String p = new File ( path ). getAbsolutePath () + File . separator ; //取得在服务器中的绝对路径 System . out . println ( "Mapping /upload/** from " + p ); registry . addResourceHandler ( "/upload/**" ) // 外部访问地址 . addResourceLocations ( "file:" + p ) // springboot需要增加file协议前缀 . setCacheControl ( CacheControl . maxAge ( 30 , TimeUnit . MINUTES )); // 设置浏览器缓存30分钟 } }

application.properties 中 file.upload.path=upload/

实际存储目录

D:/upload/2019/03081625111.jpg

(2).在Controller中增加一个RequestMapping,把文件输出到输出流中

@RestController @RequestMapping ( "/file" ) public class UploadFileController { @Autowired protected HttpServletRequest request ; @Autowired protected HttpServletResponse response ; @Autowired protected ConversionService conversionService ; @Value ( "${file.upload.path}" ) private String path = "upload/" ; @RequestMapping ( value = "/view" , method = RequestMethod . GET ) public Object view ( @RequestParam ( "id" ) Integer id ){ // 通常上传的文件会有一个数据表来存储,这里返回的id是记录id UploadFile file = conversionService . convert ( id , UploadFile . class ); // 这步也可以写在请求参数中 if ( file == null ){ throw new RuntimeException ( "没有文件" ); }   File source = new File ( new File ( path ). getAbsolutePath ()+ "/" + file . getPath ()); response . setContentType ( contentType ); try { FileCopyUtils . copy ( new FileInputStream ( source ), response . getOutputStream ()); } catch ( Exception e ) { e . printStackTrace (); } return null ; } }

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

原文链接:https://blog.csdn.net/cliche_tune/article/details/102901241

查看更多关于MultipartFile中transferTo(File file)的路径问题及解决的详细内容...

  阅读:34次