浏览器文件上传和下载 保姆级教程

本文详细介绍了前端Vue.js如何实现文件上传和下载功能,包括使用el-upload组件处理上传,定义相关参数和方法,以及后端Controller和Service层的处理逻辑。同时,展示了下载功能的实现,包括前端调用接口和处理响应,以及后端提供下载接口。文件存取工具类FileServerUtils用于文件上传和下载的辅助操作。
摘要由CSDN通过智能技术生成

浏览器文件上传和下载

前言:以下代码如果有一些类无法导入的,可以自行查资料替换!!!

1.上传

前端vue

  1. 编写按钮

    <el-button
      type="primary"
      plain
      icon="el-icon-plus"
      size="mini"
      @click="handleUpload"
      v-hasPermi="['client:clientManagement:upload']"
    >上传</el-button>
    
  2. 打开上传弹窗

    /** 上传 */
    handleUpload() {
      this.open = true;
      this.title = "上传客户端";
    },
    
  3. 编写弹窗 el-upload 绑定事件作用详情自己看官方网站

    <!-- 上传客户端 -->
    <el-dialog class="printercloud-dialog" :visible.sync="open" width="400px" append-to-body>
      <div slot="title" class="dialog-title">
        <span>{{title}}</span>
      </div>
      <el-upload
        class="upload-demo"
        drag
        ref="upload"
        :limit="1"
        accept=".zip"
        :headers="upload.headers"
        :action="upload.url"
        :disabled="upload.isUploading"
        :on-progress="handleFileUploadProgress"
        :on-success="handleFileSuccess"
        :on-change="handleChange"
        :on-remove="handleChange"
        :before-upload="beforeUpload"
        :file-list="fileList"
        :auto-upload="false">
        <i class="el-icon-upload"></i>
        <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
        <div class="el-upload__tip" slot="tip">只能上传zip文件</div>
      </el-upload>
      <div slot="footer" class="dialog-footer">
        <el-button @click="open = false">取 消</el-button>
        <el-button type="primary" @click="submitForm" v-hasPermi="['client:clientManagement:upload']">确 定</el-button>
      </div>
    </el-dialog>
    
  4. 定义相关参数

    // 弹出层标题
    title: "",
    // 是否显示弹出层
    open: false,
    // 上传参数
    upload: {
      // 是否显示弹出层(用户导入)
      open: false,
      // 弹出层标题(用户导入)
      title: '',
      // 是否禁用上传
      isUploading: false,
      // 是否更新已经存在的用户数据
      updateSupport: 0,
      // 设置上传的请求头部 权限token
      headers: { Authorization: xxx },
      // 上传文件访问的后端地址
      url: /xxx/xxx,
    },
    fileList: [],
    
  5. 定义相关方法

    /** 弹框确认上传按钮 */
    submitForm() {
      if (!this.fileList || this.fileList <= 0) {
        this.$modal.msgWarning('请选择需要上传的客户端!')
        return
      }
      this.$refs.upload.submit()
    },
    // 文件上传中处理
    handleFileUploadProgress(event, file, fileList) {
      this.upload.isUploading = true
    },
    // 文件上传成功处理
    handleFileSuccess(response, file, fileList) {
      this.upload.open = false
      this.upload.isUploading = false
      this.$refs.upload.clearFiles()
      if (response.code === 200) {
        this.$modal.msgSuccess(response.msg)
        this.getList()
      } else {
        this.$modal.msgError(response.msg)
      }
    },
    // 文件列表添加删除触发
    handleChange(file, fileList) {
      this.fileList = fileList;
    },
    // 上传去前校验
    beforeUpload(file) {
      const isJPG = file.type === 'application/zip';
      // const isLt2M = file.size / 1024 / 1024 < 2;
      if (!isJPG) {
        this.$modal.msgError('上传文件只能是 ZIP 格式!');
      }
      /* if (!isLt2M) {
        this.$message.error('上传头像图片大小不能超过 2MB!');
      } */
      // return isJPG && isLt2M;
      return isJPG;
    },
    

后端

  1. Controller接口

    /**
     * 上传客户端
     */
    @PostMapping(value = "/uploadClient", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public AjaxResult uploadClient(@ApiParam(value = "待上传文件",required = true) @RequestParam("file") MultipartFile file) throws Exception {
        return clientManagementService.uploadClient(file);
    }
    
  2. Service实现

    /**
     * 上传客户端
     * @param multipartFile
     * @return
     */
    @Override
    @Transactional
    public AjaxResult uploadClient(MultipartFile multipartFile) throws Exception {
        //创建临时目录 因为入参是MultipartFile类型,所以需要先转换成File类型,暂存在本地用于上传,上传后删除
        String parentPath = BasConfig.getUploadPath() + File.separator + IdUtils.fastSimpleUUID();
        File tempFileDir =  new File(parentPath);
        if(!tempFileDir.exists()) {
            tempFileDir.mkdirs();
        }
        try {
            String originalFilename = multipartFile.getOriginalFilename();
            // 获取文件后缀
            String prefix = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
            // 客户端名称
            String clientName = originalFilename.substring(0, originalFilename.lastIndexOf("."));
            // 根据客户端名称判断重复
            List<ClientManagement> clientList = clientManagementMapper.getClientManagementListByClientName(clientName);
            if (clientList != null && clientList.size() > 0) {
                return AjaxResult.error("客户端名称已存在");
            }
            // 用id作为文件名,防止生成的临时文件重复
            File file = new File(parentPath, IdUtils.fastSimpleUUID() + "." + prefix);
            if(!file.exists()) {
                file.createNewFile();
            }
            multipartFile.transferTo(file);
            // 文件的存储位置
            String fileID = FileServerUtils.upload(file, BasConfig.getUploadPath()+File.separator + "client/", true);
            //存到临时文件表
            ClientManagement client = new ClientManagement();
            // 获取当前用户
            LoginUser loginUser = SecurityUtils.getLoginUser();
            SysUser user = loginUser.getUser();
            client.setId(IdUtils.fastSimpleUUID());
            client.setClientName(clientName);
            client.setFileId(fileID);
            client.setFileType(prefix);
            client.setVersion("1");
            client.setIsUniversal(0);
            client.setCreateBy(user.getUserName());
            client.setCreateTime(LocalDateTime.now());
            client.setUpdateBy(user.getUserName());
            client.setUpdateTime(LocalDateTime.now());
            // 保存客户端记录
            clientManagementMapper.insertClientManagement(client);
            return AjaxResult.success("客户端上传成功");
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("客户端上传失败");
        } finally {
            // 删除本地临时文件
            delFile(tempFileDir);
        }
    }
    
    //删除临时文件
    private boolean delFile(File file){
      if(!file.exists()){
        return false;
      }
      if(file.isDirectory()){
        File[] files = file.listFiles();
        for(File f :files){
          delFile(f);
        }
      }
      return file.delete();
    }
    

2.下载

前端vue

  1. 下载按钮

    <el-button
      type="success"
      plain
      icon="el-icon-bottom"
      size="mini"
      @click="handleDownload"
    >下载</el-button>
    
  2. 相关方法

    /** 下载操作 */
    handleDownload(row) {
      const id = row.id ? row.id : this.ids[0]
      request({
        url: '/xxx/xxx/' + id + '?Authorization=' + 'xxx',// 路径、参数列表数据id、请求权限Authorization
        method: 'get',
        responseType: 'blob',// 响应类型,blob通过浏览器下载
      }).then((res) => {
      	// 我这里下载的是zip压缩包,所以正常下载type返回是application/zip,如果发生异常下载失败,返回的是application/json
        if (res.size > 0 && res.type === 'application/zip') {
          const content = res
          const blob = new Blob([content])
          if ('download' in document.createElement('a')) {
            // 非IE下载
            const elink = document.createElement('a')
            elink.download = this.selectData[0].clientName + '.' + this.selectData[0].fileType
            elink.style.display = 'none'
            elink.href = URL.createObjectURL(blob)
            document.body.appendChild(elink)
            elink.click()
            URL.revokeObjectURL(elink.href) // 释放URL 对象
            document.body.removeChild(elink)
          } else {
            // IE10+下载
            navigator.msSaveBlob(blob, fileName)
          }
        } else {
          this.$modal.msgError('客户端下载失败')
        }
      })
    },
    

后端

  1. Controller接口

    /**
     * 下载客户端
     */
    @GetMapping("/downloadClient/{id}")
    public void downloadClient(HttpServletResponse response, @PathVariable("id") @NotNull String id) throws Exception {
        clientManagementService.downloadClient(response, id);
    }
    
  2. Service实现

    /**
         * 下载客户端
         * @param response
         * @param id
         * @return
         */
        @Override
        public void downloadClient(HttpServletResponse response, String id) throws Exception {
            // 根据id获取客户端信息
            ClientManagement client = clientManagementMapper.getClientManagementById(id);
            if (client == null) {
                throw new ValidDataException("客户端信息不存在");
            }
          	// 文件再服务器上的索引
            String fileId = client.getFileId();
            if (StringUtils.isEmpty(fileId)) {
                throw new ValidDataException("服务器客户端文件不存在");
            }
            OutputStream os = null;
            InputStream fis = null;
            try {
              	// 根据文件索引,下载服务器的文件
                File file = FileServerUtils.download(fileId, null);
                fis = new FileInputStream(file);
                String formFileName = new String(client.getClientName().getBytes("UTF-8"), "ISO-8859-1");
                response.setContentType("application/zip");// 指定下载的类型,如果需要兼容下载多种类型可以自行去查资料
                response.setHeader("Content-Disposition", "attachment;filename=" + formFileName);
                os = response.getOutputStream();
                byte[] b = new byte[fis.available()];
                int len;
                while ((len = fis.read(b)) > 0) {
                    os.write(b, 0, len);
                }
                os.flush();
            } catch (Exception e) {
                e.printStackTrace();
                throw new RuntimeException("客户端下载失败");
            } finally {
                try {
                    if (os != null) {
                        os.close();
                    }
                    if (fis != null) {
                        fis.close();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    throw new RuntimeException("客户端下载失败");
                }
            }
        }
    

3.文件存取工具类FileServerUtils(也可以自行查找资料)

package com.startdima.printerCloud.common.utils;

import com.startdima.bas.common.config.BasConfig;
import com.startdima.bas.common.utils.StringUtils;
import com.startdima.common.pojo.FileResult;
import com.startdima.common.pojo.Server;
import com.startdima.file.FileServiceControl;
import net.sf.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.validation.constraints.NotNull;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 文件存取操作工具类
 */
@Component
public class FileServerUtils {
    private static final Logger logger = LoggerFactory.getLogger(FileServerUtils.class);
    private static String tempPath;
    private static Server server;

  	// 配置文件中配置的服务器路径
    @NotNull(message = "文件服务器配置不能为空")
    @Value("${serverParam}")
    public void setServerParam(String serverParam) {
        // 设置文件服务器配置
        try {
            FileServerUtils.server = new Server();
            JSONObject jsonObject = JSONObject.fromObject(serverParam);
            server.setServerParam(jsonObject.toString());
            server.setServerCode(jsonObject.getString("serverCode"));
            server.setServerType(jsonObject.getString("serverType"));
        } catch (Exception e) {
            logger.error("初始化文件服务器配置发生错误,错误原因:" + e.getMessage(), e);
        }
    }

    @Resource
    public void setTempPath(BasConfig basConfig) {
        String profile = basConfig.getProfile();
        FileServerUtils.tempPath = profile + (profile.endsWith("/") ? "" : "/") + "temp";
        // 设置缓存文件夹
        try {
            File file = new File(tempPath);
            if (!file.exists())
                file.mkdirs();
        } catch (Exception e) {
            logger.error("初始化文件操作工具类缓存文件夹发生错误,错误原因:" + e.getMessage(), e);
        }
    }

    /**
     * 判断是否为文件服务器文件id
     */
    public static boolean hasServerFile(String fileId) {
        String serverCode = server.getServerCode();
        return fileId.startsWith(serverCode + "/");
    }

    /**
     * 文件服务器文件上传
     *
     * @param file      待上传文件
     * @param storePath 文件服务器上的存储目录
     * @param delete    上传成功后是否删除本地文件
     * @return 上传后的文件名
     */
    public static String upload(File file, String storePath, boolean delete) throws Exception {
        String filename = file.getName();
        String namePrefix = filename.substring(0, filename.lastIndexOf("."));
        String nameSuffix = filename.substring(filename.lastIndexOf(".") + 1);
        // 上传的文件名
        String storeFileName = namePrefix + getTimeStr() + '.' + nameSuffix;
        // 上传文件
        FileResult fileResult = FileServiceControl.upload(server, storePath, file, storeFileName, 600);
        if (!fileResult.isFlag()) throw new Exception(fileResult.getMessage());
        String fileId = fileResult.getMessage();
        if (file.exists() && delete) file.delete();
        return fileId;
    }

    /**
     * 文件下载
     *
     * @param fileId   文件id
     * @param downPath 下载路径
     * @return 文件
     * @throws Exception 异常情况
     */
    public static File download(String fileId, String downPath) throws Exception {
        // 下载路径,为空则默认缓存路径
        if (StringUtils.isEmpty(downPath)) {
            downPath = tempPath;
        } else {
            downPath = downPath.endsWith("/") ? downPath : downPath + "/";
            File pathFile = new File(downPath);
            if (!pathFile.exists()) {
                pathFile.mkdirs();
            }
        }
        File file = new File(downPath + fileId.substring(fileId.lastIndexOf("/") + 1));
        if (file.exists()) return file;

        // 文件id切割前缀
        fileId = fileId.substring(fileId.indexOf('/'));
        FileResult result = FileServiceControl.download(server, fileId);
        if (!result.isFlag()) throw new Exception(result.getMessage());
        result.getFile().renameTo(file);
        return file;
    }

    /**
     * 删除服务器上的文件
     *
     * @param fileId 文件id
     */
    public static boolean delete(String fileId) {
        if (StringUtils.isEmpty(fileId)) return true;
        // 删除服务器上的文件
        FileResult result = FileServiceControl.delete(server, fileId);
        if (!result.isFlag()) throw new RuntimeException(result.getMessage());
        return true;
    }

    /**
     * 获取时间串
     */
    private static String getTimeStr() {
        return new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
    }
}
如果你要在Java中将重名的文件压缩并下载,你可以使用以下步骤: 1. 将要下载的文件重命名,例如给每个文件加上一个唯一的编号。 2. 将重命名后的文件压缩成一个压缩文件,例如ZIP格式。 3. 将压缩文件作为响应发送给客户端浏览器,让用户可以下载。 下面是一个示例代码,实现将多个文件压缩并下载: ```java import java.io.*; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; public class DownloadServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //获取要下载的文件列表 String[] filenames = {"file1.txt", "file2.txt", "file3.txt"}; //创建临时文件夹 File tmpdir = new File(System.getProperty("java.io.tmpdir"), "download"); tmpdir.mkdirs(); //将重名的文件重命名并复制到临时文件夹中 for (int i = 0; i < filenames.length; i++) { File srcfile = new File(filenames[i]); String newname = "file" + i + ".txt"; File dstfile = new File(tmpdir, newname); copyFile(srcfile, dstfile); } //将临时文件夹中的文件压缩成一个ZIP文件 File zipfile = new File(tmpdir, "download.zip"); zipFiles(tmpdir.listFiles(), zipfile); //设置响应头,让浏览器下载该文件 response.setHeader("Content-Disposition", "attachment; filename=\"download.zip\""); response.setContentType("application/zip"); response.setContentLength((int) zipfile.length()); //将压缩文件发送给客户端浏览器 BufferedInputStream in = new BufferedInputStream(new FileInputStream(zipfile)); BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream()); byte[] buffer = new byte[4096]; int length; while ((length = in.read(buffer)) > 0) { out.write(buffer, 0, length); } in.close(); out.flush(); out.close(); //删除临时文件夹和压缩文件 deleteDir(tmpdir); zipfile.delete(); } //复制文件 private void copyFile(File src, File dst) throws IOException { InputStream in = new FileInputStream(src); OutputStream out = new FileOutputStream(dst); byte[] buffer = new byte[4096]; int length; while ((length = in.read(buffer)) > 0) { out.write(buffer, 0, length); } in.close(); out.close(); } //压缩文件 private void zipFiles(File[] files, File zipfile) throws IOException { ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipfile)); for (File file : files) { FileInputStream in = new FileInputStream(file); out.putNextEntry(new ZipEntry(file.getName())); byte[] buffer = new byte[4096]; int length; while ((length = in.read(buffer)) > 0) { out.write(buffer, 0, length); } in.close(); } out.close(); } //删除文件夹及其内容 private void deleteDir(File dir) { for (File file : dir.listFiles()) { if (file.isDirectory()) { deleteDir(file); } else { file.delete(); } } dir.delete(); } } ``` 在上面的示例代码中,我们使用Java的ZipOutputStream类将多个文件压缩成一个ZIP文件,然后将该文件作为响应发送给客户端浏览器,让用户可以下载。在压缩过程中,我们将重名的文件重命名并复制到一个临时文件夹中,压缩完成后再删除该文件夹和压缩文件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值