Spring Boot项目实现下载项目根目录下指定目录(doc)里的文件

本文介绍了一个Java项目的文件下载功能实现过程,包括前端页面请求、后端Controller处理逻辑、自定义工具类FileUtil的设计与实现,特别针对Linux部署及浏览器兼容性问题提供了解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.页面请求下载

<a href="/downloadFile">点击下载项目中的文件</a>


2.controller接收页面下载的请求,开始下载项目中的文件,其中使用到了自定义的FileUtil类

		@RequestMapping("downloadFile")
		@ResponseBody
		public void Download(HttpServletResponse response) {
			String fileName = "ceshi1.txt";
			String result = FileUtil.downloadFile(response, fileName);
			System.out.println(result);

		} 


3.FileUtil.java工具类

   注意导包的时候,使用的是import org.springframework.util.ResourceUtils;

	/**
	 * 下载项目根目录下doc下的文件
	 * @param response response
	 * @param fileName 文件名
	 * @return 返回结果 成功或者文件不存在
	 */
	public static String downloadFile(HttpServletResponse response, String fileName) {
		File path = null;
		response.setHeader("content-type", "application/octet-stream");
		response.setContentType("application/octet-stream");
		try {
			response.setHeader("Content-Disposition", "attachment;filename=" + java.net.URLEncoder.encode(fileName, "UTF-8"));
		} catch (UnsupportedEncodingException e2) {
			e2.printStackTrace();
		}
		byte[] buff = new byte[1024];
		BufferedInputStream bis = null;
		OutputStream os = null;		
		try {
			path = new File(ResourceUtils.getURL("classpath:").getPath());
			os = response.getOutputStream();
			bis = new BufferedInputStream(new FileInputStream(new File(path + "/doc/" + fileName)));
			int i = bis.read(buff);
			while (i != -1) {
				os.write(buff, 0, buff.length);
				os.flush();
				i = bis.read(buff);
			}
		} catch (FileNotFoundException e1) {
			//e1.getMessage()+"系统找不到指定的文件";
			return "系统找不到指定的文件";
		}catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (bis != null) {
				try {
					bis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return "success";
	}


4.项目根目录下doc里放置测试文件ceshi1.txt


5、注意:如果将项目部署到linux下有可能回出现,下载文件为空,或者出现下载文件时,文件出现乱码,FileUtil.java解决方法如下

	/**
	 * 下载项目根目录下doc下的文件
	 * @param response response
	 * @param fileName 文件名
	 * @return 返回结果 成功或者文件不存在
	 */
	public static String downloadFile(HttpServletResponse response, String fileName) {
		InputStream stream = FileUtil.class.getClassLoader().getResourceAsStream("doc/" + fileName);
		response.setHeader("content-type", "application/octet-stream");
		response.setContentType("application/octet-stream");
		try {
			String name = java.net.URLEncoder.encode(fileName, "UTF-8");
			response.setHeader("Content-Disposition", "attachment;filename=" + java.net.URLDecoder.decode(name, "ISO-8859-1") );
		} catch (UnsupportedEncodingException e2) {
			e2.printStackTrace();
		}
		byte[] buff = new byte[1024];
		BufferedInputStream bis = null;
		OutputStream os = null;		
		try {
			os = response.getOutputStream();			
			bis = new BufferedInputStream(stream);
			int i = bis.read(buff);
			while (i != -1) {
				os.write(buff, 0, buff.length);
				os.flush();
				i = bis.read(buff);
			}
		} catch (FileNotFoundException e1) {
			//e1.getMessage()+"系统找不到指定的文件";
			return "系统找不到指定的文件";
		}catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (bis != null) {
				try {
					bis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return "success";
	}

6、如果在linux下部署项目,在不同浏览器下载项目内文件出现乱码的情况,参照如下解决

     6.1、前台传递参数页面

<div class="cg-title">
	<span>数达营销白皮书</span> 
	<a href=""> 
	   <img alt="" src="/static/img/icon/下载.png"> 点此下载
	</a>
</div>

    6. 2、javascript页面

//  文件下载demo
    $(".cg-title a").bind("click", function () {
        url = "/testDownFile?filename="+encodeURI($(this).prev().text());
        console.log(url)
        location.href = url;
        return false;
    })


    6.3、controller核心代码块

	@RequestMapping("testDownFile")
	@ResponseBody
	public void Download(HttpServletRequest request, HttpServletResponse response) {
		String fileName = request.getParameter("filename")+".pdf";
		System.out.println(fileName);
		String result = FileUtil.downloadFile(response, fileName, request.getHeader("User-Agent").indexOf("Trident")==-1);
		System.out.println(result);

	}

   6.4、FileUtil.java

	/**
	 * 下载项目根目录下doc下的文件
	 * @param response response
	 * @param fileName 文件名
	 * @return 返回结果 成功或者文件不存在
	 */
	public static String downloadFile(HttpServletResponse response, String fileName, boolean notIE) {
		InputStream stream = FileUtil.class.getClassLoader().getResourceAsStream("doc/" + fileName);
		response.setHeader("content-type", "application/octet-stream");
		response.setContentType("application/octet-stream");
		try {
			String name = java.net.URLEncoder.encode(fileName, "UTF-8");
			if (notIE) {
				name = java.net.URLDecoder.decode(name, "ISO-8859-1");
			}
			response.setHeader("Content-Disposition", "attachment;filename=" + name );
		} catch (UnsupportedEncodingException e2) {
			e2.printStackTrace();
		}
		byte[] buff = new byte[1024];
		BufferedInputStream bis = null;
		OutputStream os = null;		
		try {
			os = response.getOutputStream();			
			bis = new BufferedInputStream(stream);
			int i = bis.read(buff);
			while (i != -1) {
				os.write(buff, 0, buff.length);
				os.flush();
				i = bis.read(buff);
			}
		} catch (FileNotFoundException e1) {
			//e1.getMessage()+"系统找不到指定的文件";
			return "系统找不到指定的文件";
		}catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (bis != null) {
				try {
					bis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return "success";
	}








<think>我们通常将动态生成的文件(如导出的Word文档)保存到项目外部的目录(如配置的临时目录或上传目录),而不是直接写入项目的`resources`目录。原因如下: 1. **资源目录在打包后只读**:在标准的Maven/Gradle项目中,`src/main/resources`目录下的文件在打包后(如JAR或WAR)会被包含在类路径中,但运行时这些文件是只读的(在JAR内无法修改)。 2. **部署环境限制**:在生产环境中,应用通常以打包形式运行,无法直接写入JAR内部的资源文件。 3. **最佳实践**:动态生成的文件应保存在外部目录(如临时目录、配置的文件存储路径)或数据库。###替代方案:将文件生成到类路径下的`doc`目录的替代方法如果确实需要将生成的文件放在类路径下的`doc`目录(例如用于后续读取),有两种方式:1.**开发阶段**:在开发环境中,你可以直接写入到`src/main/resources/doc`目录(但需要知道项目的绝对路径)。 2. **运行阶段**:在运行时,你可以将文件写入到类路径对应的目录,但需要确保该目录文件系统中(而不是在JAR内)。这通常通过将外部目录映射到类路径来实现(如引用[1]中配置的`static-locations`)。###具体实现步骤####方案1:开发时直接写入`src/main/resources/doc`(不推荐用于生产)在开发环境中,你可以通过获取项目根路径,然后定位到`src/main/resources/doc`目录来写入文件。但请注意,这种方式在生产部署时可能失效(因为生产环境通常没有`src`目录)。示例代码(获取项目路径): ```javaimport java.nio.file.Path; importjava.nio.file.Paths; publicclass ResourcePathExample{public staticvoid main(String[]args){//获取当前工作目录项目根目录)String currentDir =System.getProperty("user.dir");Path resourcePath =Paths.get(currentDir,"src","main", "resources","doc");System.out.println("Resourcepath:" +resourcePath);} }``` 然后,你可以将生成的Word文件写入到`resourcePath`所表示的路径下。但强烈建议仅用于开发测试。####方案2:运行时写入外部目录,并映射为类路径(推荐)参考引用[1],你可以配置一个外部目录(如`E:/PictureTool/`),然后将该目录添加到静态资源路径中。这样,生成的文件可以保存在该外部目录,同时可以通过HTTP访问(如果需要)。 步骤: 1. **配置外部目录**:在`application.yml`中配置一个目录作为文件存储路径,并添加到静态资源路径。```yamlweb:upload-path:E:/PictureTool/#外部目录,根据系统调整spring:resources:static-locations: classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/,file:${web.upload-path}```这样,放在`${web.upload-path}`下的文件可以通过URL直接访问(如`http://localhost:8080/filename.docx`)。2.**将文件生成到配置的外部目录下的子目录(如`doc`)**:```javaimport org.springframework.beans.factory.annotation.Value;importorg.springframework.stereotype.Component;importjava.nio.file.Path;importjava.nio.file.Paths;@Componentpublic classFileExporter {@Value("${web.upload-path}")privateString uploadPath;//注入配置的目录public PathexportWordFile(StringfileName,byte[]content)throws IOException{//创建doc目录(如果不存在)Path docDir =Paths.get(uploadPath, "doc");if(!Files.exists(docDir)) {Files.createDirectories(docDir);}//生成文件路径PathfilePath= docDir.resolve(fileName);Files.write(filePath, content);return filePath;}}```3.**使用**:在生成Word文件后,调用`exportWordFile`方法,将文件保存到外部目录的`doc`子目录中。4.**访问文件**:如果配置了静态资源映射,可以通过`http://localhost:8080/doc/filename.docx`访问。###注意事项- **生产环境**:确保配置的外部目录存在且应用有写入权限。 -**路径分隔符**:使用`Paths.get`或`File.separator`保证跨平台兼容性。 -**清理机制**:定期清理生成的文件,避免磁盘空间不足。 ###总结在Java项目中,动态生成的文件(如导出的Word)应写入外部目录(如配置的`web.upload-path`),而不是直接写入`resources`目录(因为它是只读的)。通过配置静态资源映射,可以使这些文件能够被访问。 ###相关问题1.如何在SpringBoot中配置多个静态资源目录?2.如何实现动态生成文件的自动清理?3.在云环境中(如Docker容器),如何设置文件存储路径?4.如何通过SpringMVC提供文件下载服务?[^1]:使用Apache POI实现Java操作Office文件:从Excel、Word到PPT模板写入。[^2]: freemarker生成word的docdocx文件。</think>### 在Java项目中生成文件到resources/doc目录实现方法 在Java项目中,将动态生成的文件(如Word文档)保存到`resources/doc`目录需要特殊处理,因为资源目录在打包后通常是只读的。以下是具体实现方案: #### 最佳实践:使用相对路径写入资源目录 ```java import java.io.File; import java.io.FileOutputStream; import java.nio.file.Paths; public class ResourceFileWriter { // 获取resources/doc目录的绝对路径 private static String getResourceDocPath() { // 获取项目根目录 String projectRoot = System.getProperty("user.dir"); // 构建resources/doc完整路径 return Paths.get(projectRoot, "src", "main", "resources", "doc").toString(); } public static void saveWordToResources(XWPFDocument doc, String fileName) throws Exception { // 确保目录存在 File outputDir = new File(getResourceDocPath()); if (!outputDir.exists()) { outputDir.mkdirs(); // 创建多级目录 } // 构建完整文件路径 File outputFile = new File(outputDir, fileName); // 写入文件 try (FileOutputStream fos = new FileOutputStream(outputFile)) { doc.write(fos); } System.out.println("文件已保存到: " + outputFile.getAbsolutePath()); } } ``` #### 使用示例 ```java // 创建Word文档 XWPFDocument doc = new XWPFDocument(); // ... 填充文档内容 ... // 保存到resources/doc目录 ResourceFileWriter.saveWordToResources(doc, "exported_document.docx"); ``` #### 关键注意事项: 1. **路径获取原理**: - `System.getProperty("user.dir")` 获取当前工作目录项目根目录) - 拼接路径时使用`Paths.get()`确保跨平台兼容性 - 标准Maven项目结构:`src/main/resources/doc` 2. **运行时限制**: - 此方法**仅适用于开发环境**,当项目打包为JAR后,resources目录变为只读 - 生产环境应改用外部存储目录(如引用[1]的`web.upload-path`方案[^1]) 3. **目录创建策略**: ```java // 创建多级目录(如果不存在) outputDir.mkdirs(); ``` 会创建所有缺失的父目录 4. **路径验证技巧**: ```java System.out.println("资源目录路径: " + getResourceDocPath()); ``` 调试时输出路径,确保路径正确 #### 生产环境替代方案(推荐) 参考引用[1]的方案,使用外部可写目录[^1]: ```yaml # application.yml file: storage: path: /var/myapp/files/ # Linux路径 # path: D:/project_files/ # Windows路径 ``` ```java @Value("${file.storage.path}") private String storagePath; public void saveToExternalStorage(XWPFDocument doc, String name) throws Exception { Path outputPath = Paths.get(storagePath, "doc", name); Files.createDirectories(outputPath.getParent()); // 创建目录 try (OutputStream os = Files.newOutputStream(outputPath)) { doc.write(os); } } ``` ### 相关问题 1. 如何在Spring Boot项目中正确配置外部文件存储路径? 2. 项目打包为JAR后,如何访问动态生成的文件? 3. 如何实现跨平台的文件路径处理(Windows/Linux)? 4. 资源目录中的文件修改后,如何避免被Maven构建覆盖? [^1]: 以上提供一些依赖,是需要用到的,然后在application.yml中添加以下配置: web: upload-path: E:/PictureTool/ resources: static-locations: classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/,file:${web.upload-path} 配置web.upload-path为与项目代码分离的静态资源路径,即:文件上传保存根路径配置spring.resources.static-locations,除了带上Spring Boot默认的静态资源路径之外,加上file:${web.upload-path}指向外部的文件资源上传路径。该路径下的静态资源可以直接对外提供HTTP访问服务。 [^2]: freemarker生成word的docdocx文件。 模板制作 doc 生成 使用 Microsoft Word 等软件制作一个模板将文件转换成 Xml 格式使用 FreeMarker 语法自定义数据标签,并将文件后缀名改为.flt运行 Java 程序 docx 生成 🛠。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值