java以zip方式下载文件报错,解压时显示数据损坏

将word文件以压缩包的形式,在浏览器下载。实现报错:解压下载的zip文件,显示数据损坏,如图

img

详细代码如下:

 @PostMapping("/exportNewWord")
    public AjaxResult exportNewWord(@RequestBody Map<String, Object> params,  HttpServletResponse response) {
        try {
            Configuration configuration = new Configuration();
            configuration.setDefaultEncoding("UTF-8");
            String  masterid  = params.get("masterid").toString();
            String  domain  = params.get("domain").toString();
            Map<String, Object> map = new HashMap<>();
            Applysourcepooldetail detailQuery = new Applysourcepooldetail();
            detailQuery.setMaterid(Long.valueOf(masterid));
            List<Applysourcepooldetail> list = applysourcepooldetailService.selectApplysourcepooldetailList(detailQuery);
            if (list.size()>0) {
                for (int i = 0; i < list.size(); i++) {
                    Applysourcepooldetail detail = list.get(i);
                    if(detail.getInputvalue().contains("</")&&detail.getInputvalue().contains("/>")&&detail.getInputvalue().contains("src=")){
                        StringBuilder stringBuilder=new StringBuilder(detail.getInputvalue());
                        if (!stringBuilder.substring(1,7).contains("<img")) {
                            stringBuilder.insert(3, "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;");
                        }
                        detail.setInputvalue(stringBuilder.toString());
                        map.putAll(this.getData(map,detail,domain));
                    }else{
                        map.put(detail.getInputfield(), detail.getInputvalue());
                    }
                }
            }
            WordHtmlGeneratorHelper.handleAllObject(map);
            Template t = null;
            String filePath="";
            if(domain.contains("工业互联网平台服务商")){
                filePath = RuoYiConfig.getProfile() + "/template/exportWord.ftl";
                configuration.setDirectoryForTemplateLoading(new File(filePath).getParentFile());//模板文件所在路径
                t = configuration.getTemplate("exportWord.ftl","UTF-8"); //获取模板文件
            }else if(domain.contains("两化融合")){
                filePath = RuoYiConfig.getProfile() + "/template/exportLhrhWord.ftl";
                configuration.setDirectoryForTemplateLoading(new File(filePath).getParentFile());//模板文件所在路径
                t = configuration.getTemplate("exportLhrhWord.ftl","UTF-8"); //获取模板文件
            }else if(domain.contains("工业互联网解决方案服务商")){
                filePath = RuoYiConfig.getProfile() + "/template/resolveWord.ftl";
                configuration.setDirectoryForTemplateLoading(new File(filePath).getParentFile());//模板文件所在路径
                t = configuration.getTemplate("resolveWord.ftl","UTF-8"); //获取模板文件
            }

            File outFile = null;
            String fileName = domain;
            // s为当前用户桌面所在路径
            String tempDir = RuoYiConfig.getProfile()+File.separator;
//            fileName = fileName+".doc";
            outFile = new File(tempDir,fileName+".doc");
            if(!outFile.exists()){
                outFile.getParentFile().mkdirs();
            }
            Writer out = null;
            out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile),"UTF-8"));
            t.process(map, out); //将填充数据填入模板文件并输出到目标文件
            out.close();
            /*压缩*/
            String zipFileName = fileName + ".zip";
            String zipFilePath = tempDir + zipFileName;
            FileOutputStream fos = new FileOutputStream(zipFilePath);
            ZipOutputStream zos = new ZipOutputStream(fos);
            ZipEntry ze = new ZipEntry(fileName+".doc");

            zos.putNextEntry(ze);
            FileInputStream fis = new FileInputStream(outFile);
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = fis.read(buffer)) > 0) {
                zos.write(buffer, 0, len);
            }
            fis.close();
            zos.closeEntry();
            zos.flush();
            zos.close();
            fos.close();
            //删除服务器上的临时文件
        File deleteFile = new File(tempDir+fileName+".doc");
        deleteFile.delete();
            return AjaxResult.success(zipFilePath);
        }catch (Exception e) {
            e.printStackTrace();
        }
        return AjaxResult.success("1");
    }

    @PostMapping("/downLoadWord")
    public void download(@RequestBody Map<String, Object> params,HttpServletResponse response) throws Exception {
        String fileUrl = params.get("fileUrl").toString();
        File file = new File(fileUrl);
        String zipFileName = file.getName();
        String zipFilePath = fileUrl;
        /**
         * 下载
         */
        FileInputStream in = null;
        OutputStream out = null;
        try {
            //获取文件名
            String filename = zipFileName;
            filename = new String(filename.getBytes("iso8859-1"), "UTF-8");

            String downloadpath = zipFilePath;
            //设置响应头,控制浏览器下载该文件
            response.reset();
            response.setCharacterEncoding("UTF-8");
            response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8"));
            //读取要下载的文件,保存到文件输入流
            in = new FileInputStream(downloadpath);
            //创建输出流
            out = response.getOutputStream();
            //缓存区
            byte buffer2[] = new byte[1024];
            int len2 = 0;
            //循环将输入流中的内容读取到缓冲区中
            while ((len2 = in.read(buffer2)) > 0) {
                out.write(buffer2, 0, len2);
                out.flush();
            }
        } finally {
            //关闭
            if (in != null) {
                in.close();
            }
            if (out != null) {
                out.close();
            }
        }
        //删除服务器上的临时文件
//        File deleteFile = new File(fileUrl);
//        deleteFile.delete();
        //删除服务器上的压缩文件
        File deleteZipFile = new File(zipFilePath);
        deleteZipFile.delete();
    }

有没有人指导下

后端改完的代码如下:

/*压缩文件*/
            String zipFileName = fileName + ".zip";
           String zipFilePath = tempDir + zipFileName;
           File zipFile = new File(zipFilePath);
           if(zipFile.exists()) {
                if (zipFile.isDirectory()) {
                    FileUtils.deleteDirectory(zipFile);
                } else {
                    zipFile.delete();
                }
            }
            FileOutputStream fos = new FileOutputStream(zipFilePath);
           ZipOutputStream zos = new ZipOutputStream(fos);
           ZipEntry ze = new ZipEntry(fileName+".doc");

           zos.putNextEntry(ze);
            FileInputStream fis = new FileInputStream(outFile);
         byte[] buffer = new byte[1024];
            int len = 0;
           while ((len = fis.read(buffer)) > 0) {
               zos.write(buffer, 0, len);
            }
           zos.closeEntry();
          fis.close();
          zos.flush();
           zos.close();
           fos.close();
           return AjaxResult.success(zipFilePath);
}catch (Exception e) {
            e.printStackTrace();
        }

        return AjaxResult.success("1");
}
 @PostMapping("/downLoadWord")
    public void download(@RequestBody Map<String, Object> params,HttpServletResponse response) throws Exception {
        String fileUrl = params.get("fileUrl").toString();
        File file = new File(fileUrl);
        String zipFileName = file.getName();
        String zipFilePath = fileUrl;

        FileInputStream fis = new FileInputStream(file);

        // 创建输出流
        OutputStream out = response.getOutputStream();
        byte[] buffer = new byte[(int) file.length()];

        fis.read(buffer);
        fis.close();

        // 设置响应头
        response.setContentType("application/zip");
        response.setContentLength((int) file.length());
        response.setHeader("Content-Disposition", "attachment; filename=\"" + URLEncoder.encode(zipFileName, "UTF-8"));
        out.write(buffer);
        out.flush();
        out.close();
        //删除服务器上的临时文件
        File deleteFile = new File(fileUrl);
        deleteFile.delete();
}

前端请求代码需要将
将 responseType 设置为 'arraybuffer',以确保正确处理字节数组的响应。
详情可以参考我的创作内容里面有,希望有帮助。

这是我之前写的一个demo,你可以参考借鉴下

import java.io.*;
import javax.servlet.ServletException;
import javax.servlet.http.*;

public class DownloadFileServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String fileName = "example.docx"; // 文件名,可根据实际情况修改
        String filePath = "/path/to/file/example.docx"; // 文件路径,可根据实际情况修改

        File file = new File(filePath);
        if (file.exists()) {
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);

            byte[] buffer = new byte[1024];
            FileInputStream fis = null;
            BufferedInputStream bis = null;

            try {
                // 将Word文件打包成zip格式
                ZipOutputStream zos = new ZipOutputStream(response.getOutputStream());
                zos.putNextEntry(new ZipEntry(fileName));
                fis = new FileInputStream(file);
                bis = new BufferedInputStream(fis, 1024);
                int read;
                while ((read = bis.read(buffer, 0, 1024)) != -1) {
                    zos.write(buffer, 0, read);
                }
                zos.closeEntry();
                zos.finish();

                // 关闭流
                bis.close();
                fis.close();
                response.flushBuffer();
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            // 如果文件不存在,返回404错误
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            response.getWriter().println("File not found.");
        }
    }
}


  • 这有个类似的问题, 你可以参考下: https://ask.csdn.net/questions/732715
  • 这篇博客也不错, 你可以看下java实现文件压缩打包(zip打包)(文件相关二)
  • 除此之外, 这篇博客: 使用Java以zip形式批量下载文件、压缩文件中的 一、以zip形式批量下载文件 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • 步骤

    ① 通过response对象获取OutputStream流
    ② 设置文件ContentType类型,会判断下载文件类型
    ③ 设置文件头
    ④ 获取zip的输出流
    ⑤ 获取文件路径下的所有文件夹及文件
    ⑥ 获取此目录下的所有文件名与目录名
    ⑦ 循环读取文件路径集合,获取每一个文件的路径
    ⑧ 通过文件路径创建文件
    ⑨ 将每一个文件写入zip文件压缩包内,即进行打包
    ⑩ 最后刷新缓冲区

    代码实现:

    /**
     * 以zip形式批量下载文件
     *
     * @param response
     * @param downloadName
     * @param filePath
     */
    public static void MultiFileZipDownload(HttpServletResponse response, String downloadName, String filePath) {
        OutputStream outputStream = null;
        ZipOutputStream zos = null;
        try {
            // 通过response对象获取OutputStream流
            outputStream = response.getOutputStream();
            // 设置文件ContentType类型
            response.setContentType("multipart/form-data");
            // 设置文件头
            response.setHeader("Content-Disposition", "attachment;fileName = " + URLEncoder.encode(downloadName, "UTF-8"));
            // 获取zip的输出流
            zos = new ZipOutputStream(outputStream);
            // 获取文件路径下的所有文件夹及文件
            File dirFile = new File(filePath);
            // 获取此目录下的所有文件名与目录名
            String[] fileList = dirFile.list();
            // 循环读取文件路径集合,获取每一个文件的路径
            if (fileList != null) {
                for (String fp : fileList) {
                    File file = new File(filePath, fp);  // 通过文件路径创建文件
                    zipFile(file, zos);  // 将每一个文件写入zip文件压缩包内,即进行打包
                    // 刷新缓冲区
                    response.flushBuffer();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (zos != null) {
                    zos.close();
                }
                if (outputStream != null) {
                    outputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }