文件上传下载,解决jar包运行时下载操作报错问题

上传

具体上传的步骤可以看我写的这篇springboot跨域上传文件(图片)到Linux远程服务器(本地操作也一样)把tomcat作为文件服务器

一、使用ajax实现文件上传

1、实现本地图片预览

HTML:
<input type="file" id="chooseImage" name="myfile"  value="" class="layui-btn">
<!-- 保存用户自定义的背景图片 -->
<img style="width: 150px;height: 150px;display: none" id="cropedBigImg" value='custom' alt="lorem ipsum dolor sit" data-address='' title="自定义背景"/>
JS:(使用JQuery)
    $(function (){
        $('#chooseImage').on('change',function(){
            if ($(this)[0].files[0]==null){
                $('#cropedBigImg').css("display","none");
            }else {
                var filePath = $(this).val(),         //获取到input的value,里面是文件的路径
                    fileFormat = filePath.substring(filePath.lastIndexOf(".")).toLowerCase(),
                    src = window.URL.createObjectURL(this.files[0]); //转成可以在本地预览的格式

                // 检查是否是图片
                if( !fileFormat.match(/.png|.jpg|.jpeg/) ) {
                    $('#cropedBigImg').css("display","none");
                    error_prompt_alert('上传错误,文件格式必须为:png/jpg/jpeg');
                    return;
                }

                // $('#cropedBigImg').attr('src',src);
                $('#cropedBigImg').attr('src',src).css("display","inline-block");
            }
        });
    })    $(function (){
        $('#chooseImage').on('change',function(){
            if ($(this)[0].files[0]==null){
                $('#cropedBigImg').css("display","none");
            }else {
                var filePath = $(this).val(),         //获取到input的value,里面是文件的路径
                    fileFormat = filePath.substring(filePath.lastIndexOf(".")).toLowerCase(),
                    src = window.URL.createObjectURL(this.files[0]); //转成可以在本地预览的格式

                // 检查是否是图片
                if( !fileFormat.match(/.png|.jpg|.jpeg/) ) {
                    $('#cropedBigImg').css("display","none");
                    error_prompt_alert('上传错误,文件格式必须为:png/jpg/jpeg');
                    return;
                }

                // $('#cropedBigImg').attr('src',src);
                $('#cropedBigImg').attr('src',src).css("display","inline-block");
            }
        });
    })
样式展示:

在这里插入图片描述

2、AJAX上传文件

关键代码:
var formData = new FormData();
formData.append("myfile", $("#chooseImage")[0].files[0]);

//ajax参数:
 $.ajax({
                    type: "post",
                    url: "/index/reviseAdminInfo",
                    data: formData,
                    cache: false, //上传文件不需要缓存
                    processData: false, // 告诉jQuery不要去处理发送的数据
                    contentType: false, // 告诉jQuery不要去设置Content-Type请求头
                    success: function(data){
                    }
     )}
全部代码:
                var formData = new FormData();
                if($("#chooseImage")[0].files[0]!=null){
                    formData.append("myfile", $("#chooseImage")[0].files[0]);
                }
                formData.append("adminUserName",data.field.adminUserName);
                formData.append("adminPassword",data.field.adminPassword);
                formData.append("adminId",data.field.adminId);
                $.ajax({
                    type: "post",
                    url: "/index/reviseAdminInfo",
                    data: formData,
                    cache: false, //上传文件不需要缓存
                    processData: false, // 告诉jQuery不要去处理发送的数据
                    contentType: false, // 告诉jQuery不要去设置Content-Type请求头
                    success: function(data){
                        console.log(data==="1")
                        if (data==="1"){
                            layer.msg("修改成功",{
                                icon: 1,
                                time: 1500 //2秒关闭(如果不配置,默认是3秒)
                            },function (){
                                miniTab.deleteCurrentByIframe();
                            })
                        }else {
                            layer.msg("修改失败",{
                                icon: 2,
                                time: 2000 //2秒关闭(如果不配置,默认是3秒)
                            })
                        }
                    },
                    error: function (){
                        layer.msg("修改失败",{
                            icon: 2,
                            time: 2000 //2秒关闭(如果不配置,默认是3秒)
                        })
                    }
                });

二、springboot实现跨域文件上传

1、导入maven依赖

        <!--跨域上传文件-->
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-core</artifactId>
            <version>1.18.1</version>
        </dependency>
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-client</artifactId>
            <version>1.18.1</version>
        </dependency>

2、添加 application.yaml 文件 设置最大传输文件容量

spring:
  servlet:
    multipart:
      enabled: true
      max-file-size: 30MB
      max-request-size: 30MB

3、后端controller代码(使用UUID保证文件不重名)

这里有个坑,就是 myfile.getOriginalFilename() 这串代码是获取图片的名字,但名字带中文的话,上传会失败,所以这里我只加文件名的后缀就行, String type = myfile.getOriginalFilename().substring(myfile.getOriginalFilename().lastIndexOf(“.”));

    @PostMapping("/upLoadImg")
    @ResponseBody
    public String doRemoteUpload(MultipartFile myfile){
 
        String path = "http://{ip地址(如:127.0.0.1)}:8080/uploadfiles/";
 
//为上传到服务器的文件取名,使用UUID防止文件名重复
//        String filename= UUID.randomUUID().toString()+"-"+myfile.getOriginalFilename();
        String type = myfile.getOriginalFilename().substring(myfile.getOriginalFilename().lastIndexOf("."));
        String filename= UUID.randomUUID().toString()+type;
        try{
//使用Jersey客户端上传文件
            Client client = Client.create();
            WebResource webResource = client.resource(path +"/" + URLEncoder.encode(filename,"utf-8"));
            webResource.put(myfile.getBytes());
            System.out.println("上传成功");
            System.out.println("图片路径==》"+path+filename);
        }catch(Exception ex){
            System.out.println("上传失败");
        }
        return "随便写点,关键是看后台上传成功了吗";
    }

下载

获取根目录

springboot获取当前项目路径的地址

System.getProperty(“user.dir”)

输出目录: G:\outshine\wangsoso

//获取classes目录绝对路径

String path = ClassUtils.getDefaultClassLoader().getResource(“”).getPath();

String path = ResourceUtils.getURL(“classpath:”).getPath();

输出目录: /G:/outshine/wangsoso/target/classes/

//如果上传目录为/static/images/upload/,则可以如下获取:
File upload = new File(path.getAbsolutePath(),“static/images/upload/”);
if(!upload.exists()) upload.mkdirs();
System.out.println(“upload url:”+upload.getAbsolutePath());
//在开发测试模式时,得到的地址为:{项目跟目录}/target/static/images/upload/
//在打包成jar正式发布时,得到的地址为:{发布jar包目录}/static/images/upload/

注意:以jar包发布项目时,我们存储的路径是与jar包同级的static目录,因此我们需要在jar包目录的application.properties配置文件中设置静态资源路径,如下所示:

#设置静态资源路径,多个以逗号分隔

spring.resources.static-locations=classpath:static/,file:static/

以jar包发布springboot项目时,默认会先使用jar包跟目录下的application.properties来作为项目配置文件。

如果在不同的目录中存在多个配置文件,它的读取顺序是:

1、config/application.properties(项目根目录中config目录下)

2、config/application.yml

3、application.properties(项目根目录下)

4、application.yml

5、resources/config/application.properties(项目resources目录中config目录下)

6、resources/config/application.yml

7、resources/application.properties(项目的resources目录下)

8、resources/application.yml

注:

1、如果同一个目录下,有application.yml也有application.properties,默认先读取application.properties。

2、如果同一个配置属性,在多个配置文件都配置了,默认使用第1个读取到的,后面读取的不覆盖前面读取到的。

3、创建SpringBoot项目时,一般的配置文件放置在“项目的resources目录下”

下载代码1


    public void download(String fileName, HttpServletResponse response) {
        //  fileName要带后缀 如 123.png
        try {
            String path = new ClassPathResource("static/file/"+fileName).getFile().getPath();
// path是指想要下载的文件的路径
            File file = new File(path);
// 获取文件名
            String filename = file.getName();
// 获取文件后缀名
            String ext = filename.substring(filename.lastIndexOf(".") + 1).toLowerCase();

// 将文件写入输入流
            FileInputStream fileInputStream = new FileInputStream(file);
            InputStream fis = new BufferedInputStream(fileInputStream);
            byte[] buffer = new byte[fis.available()];
            fis.read(buffer);
            fis.close();
// 清空response
            response.reset();
// 设置response的Header
            response.setCharacterEncoding("UTF-8");
//Content-Disposition的作用:告知浏览器以何种方式显示响应返回的文件,用浏览器打开还是以附件的形式下载到本地保存
//attachment表示以附件方式下载 inline表示在线打开 "Content-Disposition: inline; filename=文件名.mp3"
// filename表示文件的默认名称,因为网络传输只支持URL编码的相关支付,因此需要将文件名URL编码后进行传输,前端收到后需要反编码才能获取到真正的名称
            response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8"));
// 告知浏览器文件的大小
            response.addHeader("Content-Length", "" + file.length());
            OutputStream outputStream = new BufferedOutputStream(response.getOutputStream());
            response.setContentType("application/octet-stream");
            outputStream.write(buffer);
            outputStream.flush();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

下载代码2:解决java项目jar打包后读取文件失败的问题,爆 D:/export-0.0.1-SNAPSHOT.jar!/BOOT-INF/classes!/stati... 错误

在本地项目读取文件时

this.getClass().getClassLoader().getResource("").getPath()+fileName
this.getClass().getResource("/filename").getPath()

都是可以成功的

但是jar打包后上面方式读取文件时 会变成 jar!filename 这样的形式去读取文件,这样是读取不到文件的

原因

原因是项目打包后Spring试图访问文件系统路径,但无法访问JAR包中的路径。

我们使用ResourceUtils.getFile(“classpath:”);这样的方式是获取不到路径的。

解决方案

我们虽然不能直接获取文件资源路径,但是我们可以通过流的方式读取资源,拿到输入流过后我们就可以对其做操作了。

关键代码

ClassPathResource resource = new ClassPathResource(&quot;\\static\\pattern\\test.txt&quot;);    // static/pattern下的 test.txt文件
InputStream in = resource.getInputStream();  //获取文件输入流d

代码

    //下载文件
    @RequestMapping("/file/download")
    public void downloadPattern(HttpServletResponse response){
        System.out.println("开始下载文件.....");
        ClassPathResource resource = new ClassPathResource("\\static\\file\\文件名.docx");
        try {
            //获取文件输入流
            InputStream in = resource.getInputStream();
            //下载文件
            downFile("文件名.docx",response,in);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * 下载文件
     * @param fileName 下载文件名称
     * @param response 响应
     * @throws IOException 异常
     */
    public static void downFile(String fileName,
                                HttpServletResponse response, InputStream in) throws IOException {
        //输出流自动关闭,java1.7新特性
        try(OutputStream os = response.getOutputStream()) {
            fileName = URLEncoder.encode(fileName, "UTF-8");
            response.reset();
            response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
            response.setContentType("application/octet-stream; charset=UTF-8");
            byte[] b = new byte[in.available()];
            in.read(b);
            os.write(b);
            os.flush();
        } catch (Exception e) {
            System.out.println("fileName=" + fileName);
            e.printStackTrace();
        } finally {
            if (in != null) {
                in.close();
            }
        }
    }

获取根路径参考:springboot获取项目的绝对路径和根目录 (shuzhiduo.com)

下载操作参考:解决java项目jar打包后读取文件失败的问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我认不到你

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值