Java Web 实现文件上传和下载接口功能

简介: Java Web 实现文件上传和下载接口功能

 1.上传java代码实现

@ResponseBody
    @PostMapping("/upload")
    public ResponseVo upload(@RequestParam(value = "file", required = false) MultipartFile multipartFile) {
        File file=new File("上传到服务器的文件地址");
        try {
            FileUtil.copy(multipartFile.getBytes(), file);
        } catch (IOException e) {
            return  ResultUtil.error();
        }
        return ResultUtil.success();
    }

image.gif

上传用post或者get请求都可以,这里代码中用post做的示例。

2.文件流下载java代码实现

文件下载除了静态访问(及nginx、tomcat等服务器映射到后的文件web路径)下载以外 ,还可以通过流的方式下载,代码如下:

/**
     * 下载
     */
    @PostMapping("/download")
    public void download(String fileName, HttpServletResponse response) throws IOException {
        FileInputStream fis=new FileInputStream("服务器文件所在路径");
        response.addHeader("Content-Disposition", "attachment;filename="+fileName+";"+"filename*=utf-8''"+fileName);
        FileUtil.copy(fis, response.getOutputStream());
    }

image.gif

上传用post或者get请求都可以,这里代码中用post做的示例。

3.Fileutil工具类代码:

import com.tarzan.navigation.common.exception.ForbiddenException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.lang.NonNull;
import org.springframework.util.Assert;
import org.springframework.util.StreamUtils;
import java.io.*;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
@Slf4j
public class FileUtil {
    /**
     * Copies folder.
     *
     * @param source source path must not be null
     * @param target target path must not be null
     */
    public static void copyFolder(@NonNull Path source, @NonNull Path target) throws IOException {
        Assert.notNull(source, "Source path must not be null");
        Assert.notNull(target, "Target path must not be null");
        Files.walkFileTree(source, new SimpleFileVisitor<Path>() {
            @Override
            public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
                    throws IOException {
                Path current = target.resolve(source.relativize(dir).toString());
                Files.createDirectories(current);
                return FileVisitResult.CONTINUE;
            }
            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
                    throws IOException {
                Files.copy(file, target.resolve(source.relativize(file).toString()),
                        StandardCopyOption.REPLACE_EXISTING);
                return FileVisitResult.CONTINUE;
            }
        });
    }
    /**
     * Deletes folder recursively.
     *
     * @param deletingPath deleting path must not be null
     */
    public static void deleteFolder(@NonNull Path deletingPath) {
        Assert.notNull(deletingPath, "Deleting path must not be null");
        if (Files.notExists(deletingPath)) {
            return;
        }
        log.info("Deleting [{}]", deletingPath);
        delete(deletingPath.toFile());
        log.info("Deleted [{}] successfully", deletingPath);
    }
    private static void delete(File file) {
        if(file.isDirectory()){
            Arrays.asList(Objects.requireNonNull(file.listFiles())).forEach(FileUtil::delete);
        }
        file.delete();
    }
    /**
     * Renames file or folder.
     *
     * @param pathToRename file path to rename must not be null
     * @param newName new name must not be null
     */
    public static void rename(@NonNull Path pathToRename, @NonNull String newName)
            throws IOException {
        Assert.notNull(pathToRename, "File path to rename must not be null");
        Assert.notNull(newName, "New name must not be null");
        Path newPath = pathToRename.resolveSibling(newName);
        log.info("Rename [{}] to [{}]", pathToRename, newPath);
        Files.move(pathToRename, newPath);
        log.info("Rename [{}] successfully", pathToRename);
    }
    /**
     * Unzips content to the target path.
     *
     * @param zis zip input stream must not be null
     * @param targetPath target path must not be null and not empty
     * @throws IOException throws when failed to access file to be unzipped
     */
    public static void unzip(@NonNull ZipInputStream zis, @NonNull Path targetPath)
            throws IOException {
        // 1. unzip file to folder
        // 2. return the folder path
        Assert.notNull(zis, "Zip input stream must not be null");
        Assert.notNull(targetPath, "Target path must not be null");
        // Create path if absent
        createIfAbsent(targetPath);
        // Folder must be empty
       ensureEmpty(targetPath);
        ZipEntry zipEntry = zis.getNextEntry();
        while (zipEntry != null) {
            // Resolve the entry path
            Path entryPath = targetPath.resolve(zipEntry.getName());
            // Check directory
            checkDirectoryTraversal(targetPath, entryPath);
            if (zipEntry.isDirectory()) {
                // Create directories
                Files.createDirectories(entryPath);
            } else {
                // Copy file
                Files.copy(zis, entryPath);
            }
            zipEntry = zis.getNextEntry();
        }
    }
    /**
     * Unzips content to the target path.
     *
     * @param bytes zip bytes array must not be null
     * @param targetPath target path must not be null and not empty
     * @throws IOException io exception
     */
    public static void unzip(@NonNull byte[] bytes, @NonNull Path targetPath) throws IOException {
        Assert.notNull(bytes, "Zip bytes must not be null");
        ZipInputStream zis = new ZipInputStream(new ByteArrayInputStream(bytes));
        unzip(zis, targetPath);
    }
    /**
     * Zips folder or file.
     *
     * @param pathToZip file path to zip must not be null
     * @param pathOfArchive zip file path to archive must not be null
     * @throws IOException throws when failed to access file to be zipped
     */
    public static void zip(@NonNull Path pathToZip, @NonNull Path pathOfArchive)
            throws IOException {
        try (OutputStream outputStream = Files.newOutputStream(pathOfArchive)) {
            try (ZipOutputStream zipOut = new ZipOutputStream(outputStream)) {
                zip(pathToZip, zipOut);
            }
        }
    }
    /**
     * Zips folder or file.
     *
     * @param pathToZip file path to zip must not be null
     * @param zipOut zip output stream must not be null
     * @throws IOException throws when failed to access file to be zipped
     */
    public static void zip(@NonNull Path pathToZip, @NonNull ZipOutputStream zipOut)
            throws IOException {
        // Zip file
        zip(pathToZip, pathToZip.getFileName().toString(), zipOut);
    }
    /**
     * Zips folder or file.
     *
     * @param fileToZip file path to zip must not be null
     * @param fileName file name must not be blank
     * @param zipOut zip output stream must not be null
     * @throws IOException throws when failed to access file to be zipped
     */
    private static void zip(@NonNull Path fileToZip, @NonNull String fileName,
                            @NonNull ZipOutputStream zipOut) throws IOException {
        if (Files.isDirectory(fileToZip)) {
            log.debug("Try to zip folder: [{}]", fileToZip);
            // Append with '/' if missing
            String folderName =
                    StringUtils.appendIfMissing(fileName, File.separator, File.separator);
            // Create zip entry and put into zip output stream
            zipOut.putNextEntry(new ZipEntry(folderName));
            // Close entry for writing the next entry
            zipOut.closeEntry();
            // Iterate the sub files recursively
            try (Stream<Path> subPathStream = Files.list(fileToZip)) {
                // There should not use foreach for stream as internal zip method will throw
                // IOException
                List<Path> subFiles = subPathStream.collect(Collectors.toList());
                for (Path subFileToZip : subFiles) {
                    // Zip children
                    zip(subFileToZip, folderName + subFileToZip.getFileName(), zipOut);
                }
            }
        } else {
            // Open file to be zipped
            // Create zip entry for target file
            ZipEntry zipEntry = new ZipEntry(fileName);
            // Put the entry into zip output stream
            zipOut.putNextEntry(zipEntry);
            // Copy file to zip output stream
            Files.copy(fileToZip, zipOut);
            // Close entry
            zipOut.closeEntry();
        }
    }
    /**
     * Creates directories if absent.
     *
     * @param path path must not be null
     * @throws IOException io exception
     */
    public static void createIfAbsent(@NonNull Path path) throws IOException {
        Assert.notNull(path, "Path must not be null");
        if (Files.notExists(path)) {
            // Create directories
            Files.createDirectories(path);
            log.debug("Created directory: [{}]", path);
        }
    }
    /**
     * The given path must be empty.
     *
     * @param path path must not be null
     * @throws IOException io exception
     */
    public static void ensureEmpty(@NonNull Path path) throws IOException {
        if (!isEmpty(path)) {
            throw new DirectoryNotEmptyException("Target directory: " + path + " was not empty");
        }
    }
    /**
     * Checks directory traversal vulnerability.
     *
     * @param parentPath parent path must not be null.
     * @param pathToCheck path to check must not be null
     */
    public static void checkDirectoryTraversal(@NonNull String parentPath,
                                               @NonNull String pathToCheck) {
        checkDirectoryTraversal(Paths.get(parentPath), Paths.get(pathToCheck));
    }
    /**
     * Checks directory traversal vulnerability.
     *
     * @param parentPath parent path must not be null.
     * @param pathToCheck path to check must not be null
     */
    public static void checkDirectoryTraversal(@NonNull Path parentPath,
                                               @NonNull String pathToCheck) {
        checkDirectoryTraversal(parentPath, Paths.get(pathToCheck));
    }
    /**
     * Checks directory traversal vulnerability.
     *
     * @param parentPath parent path must not be null.
     * @param pathToCheck path to check must not be null
     */
    public static void checkDirectoryTraversal(@NonNull Path parentPath,
                                               @NonNull Path pathToCheck) {
        Assert.notNull(parentPath, "Parent path must not be null");
        Assert.notNull(pathToCheck, "Path to check must not be null");
        if (pathToCheck.normalize().startsWith(parentPath)) {
            return;
        }
        throw new ForbiddenException("你没有权限访问 " + pathToCheck);
    }
    /**
     * Checks if the given path is empty.
     *
     * @param path path must not be null
     * @return true if the given path is empty; false otherwise
     * @throws IOException io exception
     */
    public static boolean isEmpty(@NonNull Path path) throws IOException {
        Assert.notNull(path, "Path must not be null");
        if (!Files.isDirectory(path) || Files.notExists(path)) {
            return true;
        }
        try (Stream<Path> pathStream = Files.list(path)) {
            return !pathStream.findAny().isPresent();
        }
    }
    /**
     * Copy the contents of the given input File to the given output File.
     * @param in the file to copy from
     * @param out the file to copy to
     * @return the number of bytes copied
     * @throws IOException in case of I/O errors
     */
    public static int copy(File in, File out) throws IOException {
        Assert.notNull(in, "No input File specified");
        Assert.notNull(out, "No output File specified");
        return copy(Files.newInputStream(in.toPath()), Files.newOutputStream(out.toPath()));
    }
    /**
     * Copy the contents of the given byte array to the given output File.
     * @param in the byte array to copy from
     * @param out the file to copy to
     * @throws IOException in case of I/O errors
     */
    public static void copy(byte[] in, File out) throws IOException {
        Assert.notNull(in, "No input byte array specified");
        Assert.notNull(out, "No output File specified");
        copy(new ByteArrayInputStream(in), Files.newOutputStream(out.toPath()));
    }
    /**
     * Copy the contents of the given InputStream to the given OutputStream.
     * Closes both streams when done.
     * @param in the stream to copy from
     * @param out the stream to copy to
     * @return the number of bytes copied
     * @throws IOException in case of I/O errors
     */
    public static int copy(InputStream in, OutputStream out) throws IOException {
        Assert.notNull(in, "No InputStream specified");
        Assert.notNull(out, "No OutputStream specified");
        try {
            return StreamUtils.copy(in, out);
        }
        finally {
            try {
                in.close();
            }
            catch (IOException ex) {
            }
            try {
                out.close();
            }
            catch (IOException ex) {
            }
        }
    }
    /**
     * Copy the contents of the given byte array to the given OutputStream.
     * Closes the stream when done.
     * @param in the byte array to copy from
     * @param out the OutputStream to copy to
     * @throws IOException in case of I/O errors
     */
    public static void copy(byte[] in, OutputStream out) throws IOException {
        Assert.notNull(in, "No input byte array specified");
        Assert.notNull(out, "No OutputStream specified");
        try {
            out.write(in);
        }
        finally {
            try {
                out.close();
            }
            catch (IOException ex) {
            }
        }
    }
}

image.gif

ForbiddenException 访问权限异常类

import org.springframework.http.HttpStatus;
/**
 * Exception caused by accessing forbidden resources.
 *
 * @author johnniang
 */
public class ForbiddenException extends RuntimeException {
    public ForbiddenException() {
        super();
    }
    public ForbiddenException(String message) {
        super(message);
    }
    public ForbiddenException(String message, Throwable cause) {
        super(message, cause);
    }
    public HttpStatus getStatus() {
        return HttpStatus.FORBIDDEN;
    }
}

image.gif

图片示例

image.gif编辑

image.gif编辑

image.gif编辑

完整代码请参考:

tarzan-navigation: 泰山导航网站-java版


相关文章
|
12月前
|
Java 开发工具
【Azure Storage Account】Java Code访问Storage Account File Share的上传和下载代码示例
本文介绍如何使用Java通过azure-storage-file-share SDK实现Azure文件共享的上传下载。包含依赖引入、客户端创建及完整示例代码,助你快速集成Azure File Share功能。
733 6
|
算法 安全 Java
除了类,Java中的接口和方法也可以使用泛型吗?
除了类,Java中的接口和方法也可以使用泛型吗?
314 11
|
12月前
|
Java Go 开发工具
【Java】(9)抽象类、接口、内部的运用与作用分析,枚举类型的使用
抽象类必须使用abstract修饰符来修饰,抽象方法也必须使用abstract修饰符来修饰,抽象方法不能有方法体。抽象类不能被实例化,无法使用new关键字来调用抽象类的构造器创建抽象类的实例。抽象类可以包含成员变量、方法(普通方法和抽象方法都可以)、构造器、初始化块、内部类(接 口、枚举)5种成分。抽象类的构造器不能用于创建实例,主要是用于被其子类调用。抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类abstract static不能同时修饰一个方法。
416 1
|
存储 缓存 安全
Java集合框架(二):Set接口与哈希表原理
本文深入解析Java中Set集合的工作原理及其实现机制,涵盖HashSet、LinkedHashSet和TreeSet三大实现类。从Set接口的特性出发,对比List理解去重机制,并详解哈希表原理、hashCode与equals方法的作用。进一步剖析HashSet的底层HashMap实现、LinkedHashSet的双向链表维护顺序特性,以及TreeSet基于红黑树的排序功能。文章还包含性能对比、自定义对象去重、集合运算实战和线程安全方案,帮助读者全面掌握Set的应用与选择策略。
1476 23
|
存储 数据可视化 Java
Java Stream API 的强大功能
Java Stream API 是 Java 8 引入的重要特性,它改变了集合数据的处理方式。通过声明式语法,开发者可以更简洁地进行过滤、映射、聚合等操作。Stream API 支持惰性求值和并行处理,提升了代码效率和可读性,是现代 Java 开发不可或缺的工具。
271 0
Java Stream API 的强大功能
|
存储 安全 Java
Java集合框架(一):List接口及其实现类剖析
本文深入解析Java中List集合的实现原理,涵盖ArrayList的动态数组机制、LinkedList的链表结构、Vector与Stack的线程安全性及其不推荐使用的原因,对比了不同实现的性能与适用场景,帮助开发者根据实际需求选择合适的List实现。
1368 0
|
12月前
|
算法 Java Go
【GoGin】(1)上手Go Gin 基于Go语言开发的Web框架,本文介绍了各种路由的配置信息;包含各场景下请求参数的基本传入接收
gin 框架中采用的路优酷是基于httprouter做的是一个高性能的 HTTP 请求路由器,适用于 Go 语言。它的设计目标是提供高效的路由匹配和低内存占用,特别适合需要高性能和简单路由的应用场景。
793 4
|
缓存 JavaScript 前端开发
鸿蒙5开发宝藏案例分享---Web开发优化案例分享
本文深入解读鸿蒙官方文档中的 `ArkWeb` 性能优化技巧,从预启动进程到预渲染,涵盖预下载、预连接、预取POST等八大优化策略。通过代码示例详解如何提升Web页面加载速度,助你打造流畅的HarmonyOS应用体验。内容实用,按需选用,让H5页面快到飞起!
|
JavaScript 前端开发 API
鸿蒙5开发宝藏案例分享---Web加载时延优化解析
本文深入解析了鸿蒙开发中Web加载完成时延的优化技巧,结合官方案例与实际代码,助你提升性能。核心内容包括:使用DevEco Profiler和DevTools定位瓶颈、四大优化方向(资源合并、接口预取、图片懒加载、任务拆解)及高频手段总结。同时提供性能优化黄金准则,如首屏资源控制在300KB内、关键接口响应≤200ms等,帮助开发者实现丝般流畅体验。
|
前端开发 JavaScript Shell
鸿蒙5开发宝藏案例分享---Web页面内点击响应时延分析
本文为鸿蒙开发者整理了Web性能优化的实战案例解析,结合官方文档深度扩展。内容涵盖点击响应时延核心指标(≤100ms)、性能分析工具链(如DevTools时间线、ArkUI Trace抓取)以及高频优化场景,包括递归函数优化、网络请求阻塞解决方案和setTimeout滥用问题等。同时提供进阶技巧,如首帧加速、透明动画陷阱规避及Web组件初始化加速,并通过优化前后Trace对比展示成果。最后总结了快速定位问题的方法与开发建议,助力开发者提升Web应用性能。