调用transferTo上传文件后,文件无法删除问题

25 篇文章 0 订阅

问题原因:
因为上传时判断了路径是否存在,不存在就创建,每次上传时文件前面的路径都加了一个uuid,例如:/ER7854SD4F8/测试.doc ,创建路径时使用了mkdirs方法,mkdirs方法和mkdir的方法区别在于,mkdirs可以不用管父目录是否存在,一次将路径的所有目录全部创建出来,mkdir方法需要父目录存在时才能创建;因为调用mkdirs方法时,传入的路径是文件的全路径,导致创建出来的文件是一个文件夹:

 File targetFile = new File("F:\示例\测试.doc");
        if (!targetFile.exists()) {
            targetFile.mkdirs();
        }

在这里插入图片描述
解决方法:
先创建出路径,例如:先创建这个路径(F:\示例\),在把文件的全路径放进transferTo方法中。

 String path = "F:\示例\";
 String fileName = "测试.doc";
 String filePath = "F:\示例\测试.doc";
 File targetFile = new File(path);
 if (!targetFile.exists()) {
        targetFile.mkdirs();
    }
 file.transferTo(filePath);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 这个需求比较复杂,需要用到前后端分离的技术,后端使用SSM框架,前端使用Vue框架来实现。我们分步骤来看。 1. 后端代码 1.1 实体类 我们首先需要定义一个实体类来表示Hdfs文件的基本信息,包括文件名、路径、大小、创建时间等属性。代码如下: ```java public class HdfsFile { private String name; //文件名 private String path; //文件路径 private long size; //文件大小 private Date createTime; //创建时间 //省略getter和setter方法 } ``` 1.2 DAO层 接着,我们需要定义一个DAO层来操作Hdfs文件,包括获取文件列表、上传文件删除文件等功能。代码如下: ```java public interface HdfsFileDao { //获取指定路径下的文件列表 List<HdfsFile> listFiles(String path); //上传文件 void uploadFile(String localPath, String remotePath); //删除文件或目录 void deleteFile(String path); } ``` 1.3 Service层 在Service层中,我们需要调用DAO层的方法来实现业务逻辑。代码如下: ```java @Service public class HdfsFileServiceImpl implements HdfsFileService { @Autowired private HdfsFileDao hdfsFileDao; @Override public List<HdfsFile> listFiles(String path) { return hdfsFileDao.listFiles(path); } @Override public void uploadFile(MultipartFile file, String path) throws IOException { //将MultipartFile转换为File File localFile = File.createTempFile("temp", null); file.transferTo(localFile); //上传文件 hdfsFileDao.uploadFile(localFile.getAbsolutePath(), path); //删除临时文件 localFile.delete(); } @Override public void deleteFile(String path) { hdfsFileDao.deleteFile(path); } } ``` 1.4 Controller层 在Controller层中,我们需要实现以下几个接口: 1. 获取指定路径下的文件列表 ```java @GetMapping("/list") public List<HdfsFile> listFiles(@RequestParam String path) { return hdfsFileService.listFiles(path); } ``` 2. 上传文件 ```java @PostMapping("/upload") public void uploadFile(@RequestParam("file") MultipartFile file, @RequestParam String path) throws IOException { hdfsFileService.uploadFile(file, path); } ``` 3. 删除文件 ```java @DeleteMapping("/delete") public void deleteFile(@RequestParam String path) { hdfsFileService.deleteFile(path); } ``` 2. 前端代码 2.1 文件列表组件 我们首先需要定义一个文件列表组件,用来展示Hdfs文件的基本信息。代码如下: ```vue <template> <div> <table> <thead> <tr> <th>文件名</th> <th>文件大小</th> <th>创建时间</th> <th>操作</th> </tr> </thead> <tbody> <tr v-for="file in fileList" :key="file.path"> <td>{{ file.name }}</td> <td>{{ formatSize(file.size) }}</td> <td>{{ formatDate(file.createTime) }}</td> <td> <button v-if="file.isDirectory" @click="enterDirectory(file)">进入</button> <button v-else @click="downloadFile(file)">下载</button> <button @click="deleteFile(file)">删除</button> </td> </tr> </tbody> </table> <button v-if="currentPath !== '/'" @click="goUp">返回上一级</button> </div> </template> <script> export default { props: { currentPath: { type: String, required: true, }, fileList: { type: Array, required: true, }, }, methods: { formatSize(size) { //省略代码 }, formatDate(date) { //省略代码 }, enterDirectory(file) { //省略代码 }, downloadFile(file) { //省略代码 }, deleteFile(file) { //省略代码 }, goUp() { //省略代码 }, }, } </script> ``` 2.2 文件上传组件 接着,我们需要定义一个文件上传组件,用来上传文件。代码如下: ```vue <template> <div> <input type="file" @change="selectFile" /> <button @click="uploadFile">上传</button> </div> </template> <script> export default { data() { return { file: null, } }, methods: { selectFile(event) { this.file = event.target.files[0] }, uploadFile() { if (!this.file) { alert('请选择文件') return } const formData = new FormData() formData.append('file', this.file) formData.append('path', this.currentPath) axios.post('/hdfs/upload', formData).then(() => { alert('上传成功') }) }, }, props: { currentPath: { type: String, required: true, }, }, } </script> ``` 2.3 页面组件 最后,我们需要定义一个页面组件,用来展示文件列表和文件上传组件,并提供返回上一级的功能。代码如下: ```vue <template> <div> <h1>{{ currentPath }}</h1> <file-list :file-list="fileList" :current-path="currentPath" /> <file-upload :current-path="currentPath" /> </div> </template> <script> import FileList from './FileList.vue' import FileUpload from './FileUpload.vue' export default { components: { FileList, FileUpload, }, data() { return { currentPath: '/', fileList: [], } }, mounted() { this.listFiles(this.currentPath) }, methods: { listFiles(path) { axios.get('/hdfs/list', { params: { path } }).then(response => { this.currentPath = path this.fileList = response.data }) }, goUp() { const index = this.currentPath.lastIndexOf('/') if (index === 0) { this.listFiles('/') } else { const parent = this.currentPath.substring(0, index) this.listFiles(parent) } }, }, } </script> ``` 这样,我们就完成了SSM框架分页展示Hdfs文件列表、返回上一级、进入下一级、上传文件删除文件、下载文件前后端代码的编写。 ### 回答2: SSM框架分页展示HDFS文件列表,返回上一级,进入下一级,上传文件删除文件,下载文件前后端代码如下: 前端代码:(HTML、CSS、JavaScript) ```HTML <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>HDFS文件管理</title> <style> /* CSS样式 */ /* ... 省略部分代码 .... */ </style> </head> <body> <div class="container"> <h1>HDFS文件管理系统</h1> <div id="fileListContainer"> <table id="fileListTable"> <!-- 文件列表展示表格 --> </table> </div> <div id="operationsContainer"> <button id="backBtn" onclick="goBack()">返回上一级</button> <button id="uploadBtn" onclick="uploadFile()">上传文件</button> <button id="deleteBtn" onclick="deleteFile()">删除文件</button> <button id="downloadBtn" onclick="downloadFile()">下载文件</button> </div> </div> <!-- JavaScript代码 --> <script src="jquery.min.js"></script> <script> // JavaScript代码 // ... 省略部分代码 .... </script> </body> </html> ``` 后端代码:(Java) ```java // Controller层代码 @Controller @RequestMapping("/hdfs") public class HdfsController { @Autowired private HdfsService hdfsService; @RequestMapping("/list") @ResponseBody public List<HdfsFile> getFileList(@RequestParam(value = "path", required = false, defaultValue = "/") String path, @RequestParam(value = "page", required = false, defaultValue = "1") int page, @RequestParam(value = "size", required = false, defaultValue = "10") int size) { List<HdfsFile> fileList = hdfsService.getFileList(path, page, size); return fileList; } @RequestMapping("/upload") @ResponseBody public String uploadFile(@RequestParam("file") MultipartFile file, @RequestParam("path") String path) { boolean success = hdfsService.uploadFile(file, path); if (success) { return "上传成功"; } else { return "上传失败"; } } @RequestMapping("/delete") @ResponseBody public String deleteFile(@RequestParam("path") String path) { boolean success = hdfsService.deleteFile(path); if (success) { return "删除成功"; } else { return "删除失败"; } } // ... 省略其他方法 ... } // Service层代码 @Service public class HdfsService { @Autowired private HdfsClient hdfsClient; public List<HdfsFile> getFileList(String path, int page, int size) { // 使用HdfsClient连接HDFS,获取指定路径下的文件列表 List<HdfsFile> fileList = hdfsClient.listFiles(path, page, size); return fileList; } public boolean uploadFile(MultipartFile file, String path) { // 使用HdfsClient连接HDFS,上传文件到指定路径 boolean success = hdfsClient.uploadFile(file, path); return success; } public boolean deleteFile(String path) { // 使用HdfsClient连接HDFS,删除指定路径的文件 boolean success = hdfsClient.deleteFile(path); return success; } // ... 省略其他方法 ... } // Hdfs连接客户端代码 @Component public class HdfsClient { private FileSystem fileSystem; @Value("${hadoop.hdfs.nameNode}") private String nameNode; @Value("${hadoop.hdfs.username}") private String username; @PostConstruct public void init() throws IOException, InterruptedException { Configuration conf = new Configuration(); conf.set("fs.defaultFS", nameNode); fileSystem = FileSystem.get(conf); } public List<HdfsFile> listFiles(String path, int page, int size) throws IOException { // 使用FileSystem类得到指定路径下的文件列表 FileStatus[] fileStatuses = fileSystem.listStatus(new Path(path)); List<HdfsFile> fileList = new ArrayList<>(); for (FileStatus fileStatus : fileStatuses) { HdfsFile hdfsFile = new HdfsFile(); hdfsFile.setName(fileStatus.getPath().getName()); hdfsFile.setPath(fileStatus.getPath().toString()); hdfsFile.setSize(fileStatus.getLen()); fileList.add(hdfsFile); } // 进行分页处理(根据需要) // ... return fileList; } public boolean uploadFile(MultipartFile file, String path) throws IOException { // 使用FileSystem类向指定路径上传文件 Path hdfsPath = new Path(path + "/" + file.getOriginalFilename()); FSDataOutputStream fsDataOutputStream = fileSystem.create(hdfsPath); fsDataOutputStream.write(file.getBytes()); fsDataOutputStream.close(); return true; } public boolean deleteFile(String path) throws IOException { // 使用FileSystem类删除指定路径的文件 Path hdfsPath = new Path(path); boolean success = fileSystem.delete(hdfsPath, true); return success; } // ... 省略其他方法 ... } // Hdfs文件实体类 public class HdfsFile { private String name; // 文件名 private String path; // 文件路径 private long size; // 文件大小 // getter和setter方法 // ... } ``` 以上代码是一个简单的SSM框架下展示HDFS文件列表、返回上一级、进入下一级、上传文件删除文件、下载文件的实现示例。根据实际需求和环境配置,可能还需要进行一些调整和完善。 ### 回答3: 在使用SSM框架分页展示Hdfs文件列表时,我们可以使用以下前后端代码实现返回上一级、进入下一级、上传文件删除文件和下载文件的功能。 后端代码: 1. 分页展示Hdfs文件列表: - 定义一个方法,接收当前页码和每页显示的数量作为参数。 - 使用Hadoop的Java API连接Hdfs,获取指定路径下的文件列表。 - 根据要展示的文件总数、每页显示的数量和当前页码,计算出需要展示的文件范围。 - 返回当前页需要展示的文件列表。 2. 返回上一级: - 定义一个方法,接收当前路径作为参数。 - 连接Hdfs,获取当前路径的父路径。 - 返回父路径作为上一级路径。 3. 进入下一级: - 定义一个方法,接收当前路径和选中的文件/文件夹名称作为参数。 - 将当前路径和选中的文件/文件夹名称拼接,得到下一级的路径。 - 返回下一级路径。 4. 上传文件: - 定义一个方法,接收上传文件和目标路径作为参数。 - 连接Hdfs,将上传文件保存到目标路径。 5. 删除文件: - 定义一个方法,接收需要删除文件路径作为参数。 - 连接Hdfs,删除指定路径的文件。 6. 下载文件: - 定义一个方法,接收需要下载的文件路径作为参数。 - 连接Hdfs,获取指定路径的文件流。 - 使用Spring MVC提供的ResponseEntity类,将文件流返回给前端。 前端代码: 1. 页面展示: - 使用HTML和CSS创建一个文件列表展示页面,包括文件名、文件大小、文件类型等信息,并提供返回上一级、进入下一级、上传文件删除文件和下载文件的按钮。 2. 分页处理: - 通过Ajax向后端发送请求,获取指定页的文件列表,并更新页面展示。 3. 返回上一级和进入下一级: - 通过Ajax向后端发送请求,获取上一级或下一级的路径,并更新页面展示。 4. 上传文件: - 创建一个文件上传表单,通过Ajax将选择的文件发送给后端,并更新页面展示。 5. 删除文件: - 通过Ajax向后端发送请求,删除指定文件,并更新页面展示。 6. 下载文件: - 通过Ajax向后端发送请求,获取需要下载的文件,并提供下载链接。 以上是使用SSM框架分页展示Hdfs文件列表,并实现返回上一级、进入下一级、上传文件删除文件、下载文件的简要代码示例。实际开发中,还需要进行参数验证和错误处理等操作,以保证系统的安全性和稳定性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值