开发附件页面:上传、下载、删除

35 篇文章 0 订阅
该博客详细介绍了如何在前端实现文件上传和下载功能。使用JavaScript和Ajax处理上传事件,打开上传页面,通过FastDFS存储文件,并在前端提供下载链接。在下载过程中,针对Windows和Linux环境提供了不同的处理方式,解决了跨域问题,实现了前端访问和展示虚拟资源路径。此外,还展示了FastDFS工具类的使用,用于文件上传和下载操作。
摘要由CSDN通过智能技术生成

点击事件,打开上传的页面

<a  href="javascript:void(0);" onclick="addAttachment(this)" class="ddBtn btnGreen" value="WayBill">
                    xxx附件
                </a>

function addAttachment(e) {
    var content = $(e).text().trim();
    var type = $(e).attr("value");
    var operateType = $("#operateType").val();
    var companyCheckNo = $("#companyCheckNo").val();
    art.dialog.open("/company-check/to-attachment-page?pageType="+ type +"&operateType="+ operateType + "&companyCheckNo=" + companyCheckNo , {
        type: 'POST',
        title: "添加" + content,
        lock:true,
        width: 500,
        height: 300
    });
}
/**
     * 打开附件新增页面
     */
    @RequestMapping("/to-attachment-page")
    public String toAttachmentpage(Model model,String pageType,String operateType,String companyCheckNo){
        model.addAttribute("operateType",operateType);
        model.addAttribute("pageType",pageType);
        //查询主表附件信息
        List<UploadFileVO> uploadFileVOS = new ArrayList<>();
        if ("showDetail".equals(operateType) || "edit".equals(operateType)){
            List<UploadFileDTO> uploadFileDTOS = appCompanyCheckRpcService.getFileInfoByNo(companyCheckNo,pageType);
            for (UploadFileDTO uploadFileDTO : uploadFileDTOS) {
                uploadFileVOS.add(uploadFileDTO.convert(UploadFileVO.class));
            }
        }
        model.addAttribute("uploadFileVOS",uploadFileVOS);
        return "companycheck/app_company_check_attachment";
    }

 页面

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>主表附件</title>
    <div th:replace="~{commons/head::common-header}"></div>
</head>
<body>
<div class="pA10">
    <div class="whiteBox">
        <input type="hidden" id="pageType" th:value="${pageType}"/>
        <input type="hidden" id="operateType" th:value="${operateType}"/>
        <form id="uploadForm" enctype="multipart/form-data">
            <th:block th:if="${operateType == 'edit' || operateType == 'add'}">
                <div class="row">
                    <div id="file">
                        <div>
                            <input type="file" id="uploadform-files" name="UploadForm[Files][]"
                                   multiple>
                            <div id="fileName"></div>
                        </div>
                    </div>
                </div>
            </th:block>
            <table class="commonTable editTable  mT5 table">
                <tbody id="files">
                </tbody>
            </table>
            <table class="commonTable editTable  mT5 table">
                <tbody id="existingFiles">
                <tr th:each="item: ${uploadFileVOS}">
                    <td class="hidden" th:id="${item?.id}"></td>
                    <td th:text="${item?.fileName}+ '(已上传)'"></td>
                    <td style="width: 10%"><input type="button" class="btn btnWhite downloadExisting" value="下载"></td>
                    <td style="width: 10%"><input type="button" class="btn btnRed deleteExisting" value="删除"></td>
                </tr>
                </tbody>
            </table>
        </form>
    </div>
</div>
<div th:replace="~{commons/head::common-js}"></div>
<script th:src="@{/project/js/express/companycheck/company_check_attachment.js}"></script>
<script>
    var pageType = $("#pageType").val();
    console.log("page:"+ pageType)
    var fileList = art.dialog.data(pageType + "_attachment");
    //打开弹窗时,加载未上传的文件
    $.each(fileList, function (index, item) {
        var fileName = item.name;
        allFile.push(item);
        $('#files').append( '<tr style="padding-top: 7px;">' +
            '<td>'+fileName+'(未上传)'+'</td>' +
            '<td style="width: 10%"></td>' +
            '<td style="width: 10%"><input type="button" class="btn btnRed delete" value="删除"></td>' +
            '</tr>');
        //追加文件
        formData.append('UploadForm[Files][]',item);
    });

</script>
</body>
</html>
var fileList;
var allFile = [];
//FormData对象初始化
var form = document.getElementById("uploadForm");
var pageType = document.getElementById("pageType");
var formData = new FormData(form);

$("#uploadform-files").on('change', function (e) {
    // var fileError = 0;
    $('#files').empty();
    fileList = e.currentTarget.files;
    $.each(fileList, function (index, item) {
        var fileName = item.name;
        // var fileEnd = fileName.substring(fileName.indexOf("."));
        //上传文件格式判断
        // if (fileEnd == ".xlsx") {
        allFile.push(item);
        $('#files').append( '<tr style="padding-top: 7px;">' +
            '<td>'+fileName+'(未上传)'+'</td>' +
            '<td style="width: 10%"></td>' +
            '<td style="width: 10%"><input type="button" class="btn btnRed delete" value="删除"></td>' +
            '</tr>');
        //追加文件
        formData.append('UploadForm[Files][]',item);
        // }
        // else {
        //     fileError++;
        // }
    });
    // if (fileError > 0) {
    //     alert("只能上传 “.xlsx” 格式的文件!");
    //     document.getElementById("upload-form").reset();
    //     return;
    // }

    var fileCount = $('#files').find('tr').length;
    $('#fileName').html('共上传 ' + fileCount + ' 个文件');
    art.dialog.data(pageType + "_attachment",fileList);

});

/** 删除未上传的文件*/
$('#files').on('click','.delete',function (e) {
    var saveFile = [];
    var deleteName = e.target.parentNode.previousElementSibling.previousElementSibling.textContent;
    deleteName = deleteName.substring(0, deleteName.lastIndexOf('('));
    // console.log("deleteName" + deleteName)
    var deleteIndex;
    //将不删除的放入数组中
    $.each(allFile,function (index, item) {
        if(item.name == deleteName){
            deleteIndex = index;
        }else {
            saveFile.push(item);
        }
    });
    allFile.splice(deleteIndex,1);
    formData.delete('UploadForm[Files][]');
    // 将不删除的数组追加的formData中
    $.each(saveFile,function (index, item) {
        formData.append('UploadForm[Files][]',item);
    });

    e.target.parentNode.parentNode.remove();
    var fileCount = $('#files').find('tr').length;
    $('#fileName').html('共上传 ' + fileCount + ' 个文件');

    art.dialog.data(pageType + "_attachment",saveFile);
});

/** 删除已上传的文件*/
$('#existingFiles').on('click','.deleteExisting',function (e) {
    var id = e.target.parentNode.parentNode.children[0].id
    $.pikaQajax({
        url: "/company-check/delete-attachment?id=" + id,
        type: "post",
        success: function (data) {
            if (data.status === 200) {
                e.target.parentNode.parentNode.remove();
                var fileCount = $('#files').find('tr').length;
                $('#fileName').html('共上传 ' + fileCount + ' 个文件');
            }else {
                $.alert(data.msg);
            }
        }
    });
});

/** 下载主表附件*/
$('#existingFiles').on('click','.downloadExisting',function (e) {
    var id = e.target.parentNode.parentNode.children[0].id
    $.pikaQajax({
        url: "/company-check/down-file",
        data: {"id": id},
        type: "post",
        dataType: "json",
        success: function (data) {
            if (data.status === 200) {
                var filePath = data.msg;
                if(filePath.indexOf("D:\\temp_file\\") >= 0 ) {
                    filePath = filePath.substring(13,filePath.length)
                }
                window.open(filePath);
            }else {
                $.alert(data.msg);
            }
        },
        error:function (data) {
            $.alert("操作失败,"+ data.msg);
        }
    })
});

// $("#fileUpload").on('click',function () {
//     var len = formData.getAll('UploadForm[Files][]').length;
//     $("#overlay").show();
//     if(len > 1){
//         var deleteBtn = $(".delete");
//         //通过ajax进行上传
//         $.ajax({
//             url: '/finalize/upload',
//             type: 'POST',
//             cache: false,
//             data: formData,
//             processData: false,
//             contentType: false
//         }).done(function(res) {
//             if(res.code == 'ok'){
//                 //进度条设置
//                 var value = 0;
//                 var timer2 = setInterval(function () {
//                     value ++;
//                     $("#progress").css('width', value + "%");
//                     if (value == 120) {
//                         clearInterval(timer2);
//                         $("#overlay").hide();
//                         alert("文件上传成功!");
//                     }
//                 }, 50);
//                 //删除对应按钮
//                 $("#fileUpload").css("display","none");
//                 $.each(deleteBtn,function (index, item) {
//                     $(item).css("display","none");
//                 });
//                 $('#files').append('<tr><td><td><td><a type="button" class="btn btn-success pull-right" id="fileDown" href="/finalize/get-file?id=' + res.data.id + '" >文件下载</a></td></tr>')
//             }
//
//         }).fail(function(res) {
//             alert("文件上传失败:" + res.msg);
//         });
//     }else {
//         alert("请选择需要上传的文件!");
//     }
//
// });

这里的上传我用不到,代码隐藏掉了。我是在一个子弹出层上传完文件后,关闭后,再父弹出层上进行保存,所有的文本信息和文件,一起提交到后端处理,保存。

文件是通过fastdfs上传到服务器,现在要支持下载,写一个后端支持下载的功能,期间碰到跨域的问题,前端无法访问跨域的文件地址,试了其他方法,有很多可以解决的办法,下面是我的写法,前端可以访问,并展示的虚拟资源路径。

/**
     * 下载
     */
    @RequestMapping("/down-file")
    @ResponseBody
    public ApiResponses<Void> getDownUrl(String id, HttpServletResponse res){
        UploadFileDTO uploadFileDTO = uploadFileRpcService.getFileById(id);
        if (StringUtils.isBlank(uploadFileDTO.getFilePath())){
            return ApiResponses.failure(new ErrorCode("文件URL路径不存在!",500,true,"文件URL路径不存在"));
        }
        String netPath = storageUrl + uploadFileDTO.getFilePath();
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        File file = null;
        //删除之前的临时文件
        FileUtils.deleteDirectory("D:/temp_file");
        try {
            URL url = new URL(netPath);
            HttpURLConnection connection =  (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            connection.connect();
            InputStream is = connection.getInputStream();
            bis = new BufferedInputStream(is);
            file = new File("D:/temp_file");
            if(!file.exists()){//如果文件夹不存在
                file.mkdir();//创建文件夹
            }
            file = new File("D:/temp_file/" + uploadFileDTO.getFileName());//获取文件名
            FileOutputStream fos = new FileOutputStream(file);
            bos = new BufferedOutputStream(fos);
            int b = 0;
            byte[] byArr = new byte[1024*4];
            while((b=bis.read(byArr))!=-1){
                bos.write(byArr, 0, b);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            try {
                if(bis!=null){
                    bis.close();
                }
                if(bos!=null){
                    bos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return success( file.getPath());
    }

上面的下载方法适合widows部署环境,如果是linux环境的话,上面的下载方法不能用。

linux 环境的换成下面写法:

/**
     * 下载
     */
    @RequestMapping("/down-file")
    public void getDownUrl(String id, HttpServletResponse res) throws IOException, MyException {
        UploadFileDTO uploadFileDTO = uploadFileRpcService.getFileById(id);
        if (StringUtils.isBlank(uploadFileDTO.getFilePath())){
            return ;
        }
        String netPath = storageUrl + uploadFileDTO.getFilePath();

        //取出正数第三个“/”后面的内容
        String[] split = netPath.split("\\/", 4);//分4部分,第一部分为http:  第二部分为空格  第三部分为ip和端口 第四部分为其他
        String fileId = split[3];
        byte[] download = fastDFSUtils.downloadByFileId(fileId);
        OutputStream os = response.getOutputStream();

        // 设置响应头
        // 文件编码 处理文件名中的 '+'、' ' 特殊字符
        String encoderName = URLEncoder.encode(uploadFileDTO.getFileName(), "UTF-8").replace("+", "%20").replace("%2B", "+");
        response.setHeader("Content-Disposition", "attachment;filename=\"" + encoderName + "\"");
        response.setContentType("multipart/form-data" + ";charset=UTF-8");//设置文件ContentType类型,这样设置,会自动判断下载文件类型
        response.setHeader("Accept-Ranges", "bytes");

        ByteArrayInputStream is = new ByteArrayInputStream(download);
        byte[] buffer = new byte[1024 * 5];
        int len = 0;
        while ((len = is.read(buffer)) > 0) {
            os.write(buffer, 0, len);
        }
        os.flush();
    }

前端用a标签下载

<a href="javascript:void(0)" th:href="'/company-check/down-file?id='+${item.getTranLicFileId()}"><i class="fa fa-download ui-datepicker-trigger" style="top: 10px;"></i></a>

附上fastDFs工具类

import lombok.extern.slf4j.Slf4j;
import org.csource.common.MyException;
import org.csource.common.NameValuePair;
import org.csource.fastdfs.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.system.ApplicationHome;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;

@Slf4j
@Component
public class FastDfsUtil {
    @Value("${fastdfs.storage_servers}")
    private String storageUrl;

    @Value("${spring.profiles.active}")
    private String propertyType;

    /**
     * 根据fileId从trackerServer获取可用storageServer并返回字节数组
     *
     * @param fileId
     * @return
     * @throws IOException
     * @throws MyException
     */
    public byte[] downloadByFileId(String fileId) throws IOException, MyException {
        ClientGlobal.initByProperties(getFastDfsProperties());
        TrackerClient tracker = new TrackerClient();
        TrackerServer trackerServer = null;
        try {
            trackerServer = tracker.getConnection();
            StorageServer storageServer = null;
            StorageClient1 client = new StorageClient1(trackerServer, storageServer);
            byte[] re = client.download_file1(fileId);
            return re;
        } catch (IOException | MyException e) {
            throw e;
        } finally {
            trackerServer.close();
        }
    }


    /**
     * 根据fileId从trackerServer获取可用storageServer并返回字节数组
     *
     * @param fileId
     * @return
     * @throws IOException
     * @throws MyException
     */
    public byte[] getFileList(String fileId) throws IOException, MyException {
        ClientGlobal.initByProperties(getFastDfsProperties());
        TrackerClient tracker = new TrackerClient();
        TrackerServer trackerServer = null;
        try {
            trackerServer = tracker.getConnection();
            StorageServer storageServer = null;
            StorageClient1 client = new StorageClient1(trackerServer, storageServer);
            byte[] re = client.download_file1(fileId);
            return re;
        } catch (IOException | MyException e) {
            throw e;
        } finally {
            trackerServer.close();
        }
    }
    /**
     * fastdfs文件上传
     *
     * @param file 属于MultipartFile类型
     * @return
     * @throws IOException
     * @throws MyException
     */
    public String fileUpload(MultipartFile file) throws IOException, MyException {
        if (file.isEmpty()) {
            return null;
        } else {
            String tempFileName = file.getOriginalFilename();
            //fastDFS方式
            ClientGlobal.initByProperties(getFastDfsProperties());
            byte[] fileBuff = file.getBytes();
            String fileId = "";
            String fileExtName = tempFileName.substring(tempFileName.lastIndexOf(".") + 1);

            //建立连接
            TrackerClient tracker = new TrackerClient();
            TrackerServer trackerServer = tracker.getConnection();
            StorageClient1 client = new StorageClient1(trackerServer, null);

            //设置元信息
            NameValuePair[] metaList = new NameValuePair[3];
            metaList[0] = new NameValuePair("fileName", tempFileName);
            metaList[1] = new NameValuePair("fileExtName", fileExtName);
            metaList[2] = new NameValuePair("fileLength", String.valueOf(file.getSize()));

            //上传文件,获得fileId
            fileId = client.upload_file1(fileBuff, fileExtName, metaList);
            return fileId;
        }
    }

    /**
     * 获取FastDfs配置
     */
    private String getFastDfsProperties() {
        String CLASS_PATH = "";
        ApplicationHome home = new ApplicationHome();
        File file = home.getSource();
        if(file != null && file.exists()){ //外部配置
            CLASS_PATH = file.getParentFile().getPath() + File.separator + "config" + File.separator;
//            log.info("外部配置:" + CLASS_PATH + "application-" + propertyType + ".properties");
            return CLASS_PATH + "application-" + propertyType + ".properties";
        }else{
//            log.info("外部配置为空" + "application-" + propertyType + ".properties");
            return "application-" + propertyType + ".properties";
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值