文件上传和下载

1、文件下载

  1. 要获取下载文件的路径

  2. 下载的文件名是啥?

  3. 设置想办法让浏览器能够支持下载我们需要的东西

  4. 获取下载文件的输入流

    IO

  5. 创建缓冲区

  6. 获取OutputStream对象

  7. 将FileOutputStream流写入到buffer缓冲区

  8. 使用OutputStream将缓冲区的数据输出到客户端

public class FileServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       //1.  要获取下载文件的路径
       String realPath="D:\\ideaProtect\\excel\\servlet\\src\\main\\resources\\1.ico";
       //2. 下载的文件名是啥?分割最后一个/,下一个部分就是文件名
       String fileName=realPath.substring(realPath.lastIndexOf("\\")+1);
       //3. 设置想办法让浏览器能够支持(Content-Disposition)下载我们需要的东西,中文文件名需要URLEncoder.encode(),否则有可能乱码
       resp.setHeader("Content-Disposition","attachment;filename"+fileName+
               URLEncoder.encode(fileName,"UTF-8"));
       //4. 获取下载文件的输入流
       FileInputStream fileInputStream=new FileInputStream(realPath);
       //5. 创建缓冲区
       int len=0;
       byte[] buffer = new byte[1024];
       //6. 获取OutputStream对象
        ServletOutputStream outputStream=resp.getOutputStream();
       //7. 将FileOutputStream流写入到buffer缓冲区
       while ((len=fileInputStream.read(buffer))>0){
           outputStream.write(buffer,0,len);
       }     
       //关闭流
       fileInputStream.close();
       outputStream.close();
    }
    
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

    }

前端需要用blob接收io流

2、文件上传

导入依赖

        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.4</version>
        </dependency>

        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>
方式一:
</%--通过表单上传文件
	get:上传文件大小有限制
	post:上传文件大小没有限制>
<form action="" enctype="multipart/form-data" method="post">
    <input type="file" name="file1">
    <input type="submit"> <input type="reset">
</form>
 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //判断上传的文件是普通表单还是文件表单
        if(ServletFileUpload.isMultipartContent(req)){
            return;//终止方法运行,说明这是一个普通的表单,直接返回
        }//如果通过了这个if,说明我们的表单是带上传文件的

        try {
            //创建上传文件的保存路径,建议在WEB-INF路径下,安全,用户无法直接访问上传的文件
            String uploadPath =this.getServletContext().getRealPath("/resource/upload");
            File uploadFile = new File(uploadPath);
            if (!uploadFile.exists()){
                uploadFile.mkdir();//创建这个目录
            }

            //缓存,临时文件,假设文件大小超过预期,我们就把她放到一个临时文件中,过几天会自动删除,或提示用户转存为永久
            String tmpPath =this.getServletContext().getRealPath("/resource/tmp");
            File tmpFile = new File(tmpPath);
            if (!tmpFile.exists()){
                uploadFile.mkdir();//创建这个目录
            }

            //处理上传的文件,一般都需要通过流来获取,我们可以使用request.getInputStream(),原生态的文件上传流获取,十分麻烦
            //但是我们都建议使用Apache的文件上传组件来实现,common-fileupload,它需要依赖于common-io组件


            /**
             * servletFileUpload负责处理上传的文件数据,并将表单中每个输入项封装成一个FileItem对象,
             * 在使用ServletFileUpload对象解析请求时需要DiskFileItemFactory对象
             * 所以,我们需要在进行解析工作前构造好DiskFileItemFactory对象
             * 通过ServletFileUpload对象的构造方法或setFileItemFactory()方法设置ServletFileUpload对象的fileItemFactory属性
             */

            //1、创建DiskFileItemFactory对象,处理文件上传路径或者大小限制的:
            DiskFileItemFactory factory=new DiskFileItemFactory();
            //通过这个工厂设置一个缓冲区,当上传的文件大于这个缓冲区的时候,将他放到临时文件中:(可不写)
            factory.setSizeThreshold(1024*1024);
            factory.setRepository(tmpFile);

            //2、获取ServletFileUpload
            ServletFileUpload upload = new ServletFileUpload(factory);

            //监听文件上传进度:(可不写)
            upload.setProgressListener(new ProgressListener() {
                @Override
                public void update(long pBytesRead, long pContentLength, int pItems) {
                    System.out.println("已上传 : " + pBytesRead + ", 总大小 : " + pContentLength + ", pItems = " + pItems);
                }
            });

            //处理乱码问题(可不写)
            upload.setHeaderEncoding("UTF-8");
            //设置单个文件的最大值
            upload.setFileSizeMax(1024*1024*10);
            //设置总共能上传文件的大下
            //1024=1kb*1024=1M*10=10M
            upload.setSizeMax(1024*1024*10);

            //3、处理上传的文件,把前端请求解析,封装成一个FileItem对象
            List<FileItem> fileItems=upload.parseRequest(req);
            //fileItem表单对象
            for (FileItem fileItem : fileItems) {
                //判断上传的文件是普通的表单还是带文件的表单
                if (fileItem.isFormField()){
                    //getFiledName指的是前端表单控件的name;
                    String name=fileItem.getFieldName();
                    String value=fileItem.getString("UTF-8");
                    System.out.println(name+":"+value);
                }else{//文件情况
                    //1、处理文件
                    String uploadFileName=fileItem.getName();
                    //可能存在文件名不合法的情况
                    if (uploadFileName.trim().equals("")||uploadFileName==null){
                        continue;
                    }
                    //获得上传的文件名
                    String fileName=uploadFileName.substring(uploadFileName.lastIndexOf("/")+1);
                    //获得文件后缀名
                    String fileExtName=uploadFileName.substring(uploadFileName.lastIndexOf(".")+1);
                    //如果文件后缀名fileExtName不是我们需要的,直接return不处理,搞事用户文件类型不对

                    //可以使用UUID(唯一识别的通用码),保证文件名唯一
                    //UUID.randomUUID(),随机生成一个唯一识别的通用码

                    //网络传输中的东西都需要序列化
                    //POJO,实体类,如果想要在多个电脑上运行,传输===>需要把对象序列化
                    //implements Serialzable ;标记接口,jvm--->本地方法栈 native-->c++
                    String uuidPath = UUID.randomUUID().toString();
                    //2、存放地址,存放到uploadPath,文件真实存放的路径realPath
                    String realPath = uploadPath+"/"+uuidPath;
                    //给每个文件创建一个对应的文件夹
                    File realPathFile=new File(realPath);
                    if (!realPathFile.exists()){
                        realPathFile.mkdir();
                    }

                    //3、文件传输
                    //获得文件上传的流
                    InputStream inputStream=fileItem.getInputStream();
                    //创建一个文件输出流
                    //realPath=真实的文件夹
                    //差了一个文件;加上输出的文件的名字+"/"+uuidFileName
                    FileOutputStream fos=new FileOutputStream(realPathFile+"/"+fileName);
                    //创建一个缓冲区
                    byte[] buffer=new byte[1024*1024];
                    //判断是否读取完毕
                    int len=0;
                    //如果大于0说明还在存数据
                    while ((len=inputStream.read(buffer))>0){
                        fos.write(buffer,0,len);
                    }
                    //关闭流
                    fos.close();
                    inputStream.close();

                    fileItem.delete();//上传成功,清除临时文件

                }
            }
        } catch (FileUploadException e) {
            e.printStackTrace();
        }


    }
 String format = sdf.format(new Date());
        String realPath = req.getServletContext().getRealPath("/upload") + format;
        File folder = new File(realPath);
        if (!folder.exists()) {
            folder.mkdirs();
        }
        String oldName = file.getOriginalFilename();
        String newName = UUID.randomUUID().toString() + oldName.substring(oldName.lastIndexOf("."));
        file.transferTo(new File(folder,newName));
        String url = req.getScheme() + "://" + req.getServerName() + ":" + req.getServerPort() + "/upload" + format + newName;
        System.out.println(url);
方式二:
  1. 文件上传:

    SimpleDateFormat sdf = new SimpleDateFormat("/yyyy/MM/dd/");
        @PostMapping("/uploadQuestionFile")
        public void uploadQuestionFile(HttpServletRequest req,@RequestBody MultipartFile file,FileServlet fileServlet) throws ServletException, IOException {
            String format = sdf.format(new Date());
            String realPath = req.getServletContext().getRealPath("/upload") + format;
            File folder = new File(realPath);
            if (!folder.exists()) {
                folder.mkdirs();
            }
            String oldName = file.getOriginalFilename();
            String newName = UUID.randomUUID().toString() + oldName.substring(oldName.lastIndexOf("."));
            file.transferTo(new File(folder,newName));
            String url = req.getScheme() + "://" + req.getServerName() + ":" + req.getServerPort() + "/upload" + format + newName;
            System.out.println(url);
    
            String downloadPath="D:\\download\\试题解析.xlsx";
            File file1=new File(downloadPath);
            if (!file1.exists()){
                file1.createNewFile();
            }
            FileServlet.downloadUsingNIO(url, "D:\\download\\试题解析.xlsx");
        }
    
    
  2. 根据url获取上传的文件的流

    • 方式一:

      public static void downloadUsingNIO(String urlStr, String file) throws IOException {
              URL url = new URL(urlStr);
      
              ReadableByteChannel rbc = Channels.newChannel(url.openStream());
      
              FileOutputStream fos = new FileOutputStream(file);
      
              fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
      
              fos.close();
      
              rbc.close();
      
          }
      
    • 方式二:

          public static void downloadUsingStream(String urlStr, String file) throws IOException{
              URL url = new URL(urlStr);
      
              BufferedInputStream bis = new BufferedInputStream(url.openStream());
      
              FileOutputStream fis = new FileOutputStream(file);
      
              byte[] buffer = new byte[1024];
      
              int count=0;
      
              while((count = bis.read(buffer,0,1024)) != -1)
      
              {
                  fis.write(buffer, 0, count);
      
              }
      
              fis.close();
      
              bis.close();
          }
      
      
  3. vue前端

    <div style="margin:50px">
      <el-upload
        ref="upload"
        class="upload-demo"
        action="api/uploadQuestionFile"
        :auto-upload="false"
      >
        <template #trigger>
          <el-button size="small" type="primary">select file</el-button>
        </template>
        <el-button
          style="margin-left: 10px"
          size="small"
          type="success"
          @click="submitUpload"
          >upload to server</el-button
        >
        <template #tip>
          <div class="el-upload__tip">
            jpg/png files with a size less than 500kb
          </div>
        </template>
      </el-upload>
    </div>
              
      submitUpload() {
          this.$refs.upload.submit()
        }
    
posted @   lim_sy  阅读(185)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示