前后端交互一(ajax的封装,formData实现多文件上传,qq空间批量上传图片案例)

84 篇文章 3 订阅
7 篇文章 1 订阅

1.重点掌握及知识点

重点掌握:

  1. XMLHttpRequest对象的使用
  2. ajax的封装使用
  3. 利用node搭建服务器提供数据
  4. FormData对象的使用
  5. 利用formData实现多文件上传
  6. qq空间批量上传图片案例

知识点:

  • XMLhttpRequet的使用
  • 会使用ajax进行数据交互
  • 会使用node搭建服务器
  • 学会使用FormData来上传文件

1.跨域 : 非同源;  2. 非跨域: 同源;

协议 -- 域名  -- 端口 ;  都相同 同源;(同一个服务器);

如,http(https):// www.kaikeba.com:80/news/index?id=1

localhost  / 127.0.0.1;本地  ip 

2.ajax封装

封装步骤:

  1. 使用Object.assign()函数将默认配置和传递配置参数进行合并;
  2. 传递的method中,需要判断get/post,get传参需要使用queryString即使用?进行拼接url;post也要凭借成参数并通过send()进行传递;
  3. 封装拼接url方法(Object.keys(obj)和Object.values(obj)),map循环key=value并使用join("&")进行拼接(这种方式如果数据对象为多层数据,需要递归解决);
  4. onload()方法获取返回数据,xhr.responseText()
  5. 判断get/post方法,不同请求方式,send()方法不同。
  6. 需要给出默认headers配置,用户也可以自定义设置,通过for in设置头部setRequestHeader();设置头部后,需要switch判断头部,只有为JSON时,才能以封装的数据格式以post方式传递数据,如果是json格式,需要转为json再发送
  7. onload()时也需要判断返还数据类型,或者直接使用JSON.parse()直接数据转为对象

封装成类似下面形式:

            ajax({
            url: "/xml",
            method: "post",
            data: {
                hello: "你好",
                height: "178cm"
            },
            success(res) {
                console.log(res)
            }
        })

 ajax.js:

class MyAjax {
    constructor(options) {
        // 将传入的配置和默认配置进行合并
        this.options = this.ajax(options);
    }
    ajax(options) {
        let xhr = new XMLHttpRequest();
        // 注意assign()方法是将后面的输入配置合并前面的默认配合(注意需要opts接收后才是合并后的对象)
        let opts = Object.assign({
            // 因为get/post请求不同带参方式不同,所以需要拼接url
            url: '',
            method: 'get',
            data: '',
            headers:{
                "content-type":"application/x-www-form-urlencoded",
            },
            success(res) {}
        }, options);
        // 判断get请求时拼接url
        if (opts.method === "get") {
            opts.url = olUrl(opts);
        }
        // 发送请求
        xhr.open(opts.method, opts.url, true);

        // 循环设置头部(可能会有不同的头部信息,不只是content-type),注意设置头部必须在open()方法之后
        for(let header in opts.headers){
            xhr.setRequestHeader(header, opts.headers[header]);
        }
        // 根据不同头部信息,发送请求不同
        let sendData;
        
        switch(opts.headers['content-type']){
            // 如果请求头content-type为application/x-www-form-urlencoded直接拼接参数
            case 'application/x-www-form-urlencoded':
                sendData = olUrl(opts);
                break;
            case 'application/json':
                sendData = JSON.stringify(opts.data);
                break;
        }

        // 获取返回数据(需要设置到options中的success,在调用时才能使用success()获得返回数据)
        xhr.onload = function(){
            // 用户名密码都正确时会返回页面
            if(xhr.responseText.startsWith("<!DOCTYPE html>")){
                opts.success({
                    msg:"校验成功",
                    code:4
                });
            }else{
                opts.success(JSON.parse(xhr.responseText));//返回数据全部转为对象
            }
        }

        // 判断如果是post请求需要将请求数据一并发送
        if (opts.method === "get") {
            xhr.send();
        } else {
            xhr.send(sendData);
        }

        // 拼接url(只有get请求需要拼接)
        function olUrl(options) {
            let keys = Object.keys(options.data);
            let values = Object.values(options.data);
            let queryString = keys.map((key, index) => {
                return key + '=' + values[index];
            }).join("&");
            return options.url + "?" + queryString;
        }
    }
}
// 通过定义函数new MyAjax(options),返回MyAjax对象
function ajax(options) {
    return new MyAjax(options);
}
export default ajax;

3.通过formData实现《qq空间批量上传图片》

  • 需求确定:相册内容显示相册

  • nodejs搭建后台

  • 分析上传元素

    1. 登录区分不同用户

    2. 创建上传对象

    3. 上传图片

    4. 获取上传后的最新图片数据

3.1需求确定

3.1.1相册内容显示相册

点击上传(可选择多张图片),上传成功后,会显示相册图片;

上传时,有上传进度显示

3.2nodejs搭建后台

使用nunjucks加载页面

3.3分析上传元素

3.3.1登录区分不同用户

3.3.2创建上传对象

  1. 上传图片可以有多张图片:input中使用multiple="multiple"即可选择多张上传图片;
  2. 获取并显示待上传图片:通过原生this.files可以获取所有图片对象。根据文件对象循环创建HTML(createElement("div"))放入对应容器中;
  3. 通过FileReader读取上传文件。let fileReader = new FileReader(file);fileReader.readAsDataURL(file);fileReader.onload()时将图片转为base64,并将base64作为临时路径(即在onload时再创建HTML);
  4. 继续添加时,继续创建HTML;

3.3.3上传图片

  1. 上传:监控上传进度,后台转存;此处上传是一个接一个进行上传,将需要上传时将html中对象一个一个添加到数组中,上传时将每个图片抽象成图片类(每张图片都有自己的创建HTML,监控上传进度,上传等方法);
  2. 将创建的节点进行保存,用于监控上传进度;
  3. 通过FormData进行上传
  4. 通过unload中的onprogress监控上传进度,onload()处理上传成功后的处理;
  5. 点击上传时,遍历存储的图片数组,并进行上传
  6. 使用Promise监控一个一个上传:调用时返回Promise对象,在每一个上传的函数中,使用async await处理即可

3.3.4获取上传后的最新图片数据

3.4完整案例展示

 

4.总结

  1. XMLHttpRequest对象的使用
  2. ajax的封装使用
  3. 利用node搭建服务器提供数据
  4. FormData对象的使用
  5. 利用formData实现多文件上传
  6. 通过async和await处理异步
  7. qq空间批量上传图片案例
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
前端代码(HTML、JavaScript、JSP): ```html <!-- 文件列表展示 --> <table> <thead> <tr> <th>文件名</th> <th>文件大小</th> <th>上传时间</th> <th>操作</th> </tr> </thead> <tbody id="fileList"></tbody> </table> <!-- 分页 --> <div class="pagination"> <ul> <li><a href="javascript:void(0);" onclick="getPageData(1)">首页</a></li> <li><a href="javascript:void(0);" onclick="getPageData(currentPage-1)">上一页</a></li> <li><a href="javascript:void(0);" onclick="getPageData(currentPage+1)">下一页</a></li> <li><a href="javascript:void(0);" onclick="getPageData(totalPages)">末页</a></li> <li><a href="javascript:void(0);">共<span id="totalPages"></span>页</a></li> <li><a href="javascript:void(0);">当前第<span id="currentPage"></span>页</a></li> </ul> </div> <!-- 上传文件 --> <form id="uploadForm" enctype="multipart/form-data"> <input type="file" name="file" /> <button type="submit" onclick="uploadFile()">上传</button> </form> <!-- 删除文件 --> <button onclick="deleteFile()">删除</button> <!-- 下载文件 --> <a id="downloadLink" href="#" download></a> <script> var currentPage = 1; // 当前页码 var totalPages = 0; // 总页数 // 获取文件列表数据 function getPageData(page) { currentPage = page; $.ajax({ url: "/file/list", type: "GET", data: { pageNum: currentPage }, success: function(result) { // 处理返回的数据 $("#fileList").html(""); $.each(result.records, function(index, item) { var tr = "<tr>" + "<td>" + item.fileName + "</td>" + "<td>" + item.fileSize + "</td>" + "<td>" + item.uploadTime + "</td>" + "<td><input type='checkbox' name='fileId' value='" + item.id + "' /></td>" + "</tr>"; $("#fileList").append(tr); }); // 更新分页信息 totalPages = result.pages; $("#totalPages").text(totalPages); $("#currentPage").text(currentPage); } }); } // 上传文件 function uploadFile() { var formData = new FormData($("#uploadForm")[0]); $.ajax({ url: "/file/upload", type: "POST", data: formData, contentType: false, processData: false, success: function() { alert("上传成功!"); getPageData(currentPage); }, error: function() { alert("上传失败!"); } }); } // 删除文件 function deleteFile() { var fileIds = $("input[name='fileId']:checked").map(function() { return $(this).val(); }).get(); if (fileIds.length == 0) { alert("请选择要删除的文件!"); return; } $.ajax({ url: "/file/delete", type: "POST", data: { fileIds: fileIds.join(",") }, success: function() { alert("删除成功!"); getPageData(currentPage); }, error: function() { alert("删除失败!"); } }); } // 下载文件 function downloadFile(fileId) { $("#downloadLink").attr("href", "/file/download?fileId=" + fileId); $("#downloadLink").get(0).click(); } // 页面加载完成时获取第一页数据 $(function() { getPageData(1); }); </script> ``` 后端代码(Java): ```java @Controller @RequestMapping("/file") public class FileController { @Autowired private FileSystem fileSystem; // 分页展示文件列表 @GetMapping("/list") @ResponseBody public ResultVO<PageInfo<FileVO>> listFiles(@RequestParam(defaultValue = "1") Integer pageNum, @RequestParam(defaultValue = "10") Integer pageSize) { List<FileVO> fileVOList = new ArrayList<>(); try { RemoteIterator<LocatedFileStatus> fileStatusList = fileSystem.listFiles(new Path("/"), true); while (fileStatusList.hasNext()) { LocatedFileStatus fileStatus = fileStatusList.next(); FileVO fileVO = new FileVO(); fileVO.setId(UUID.randomUUID().toString()); fileVO.setFileName(fileStatus.getPath().getName()); long fileSize = fileStatus.getLen(); if (fileSize < 1024) { fileVO.setFileSize(fileSize + " B"); } else if (fileSize < 1048576) { fileVO.setFileSize(fileSize / 1024 + " KB"); } else { fileVO.setFileSize(fileSize / 1048576 + " MB"); } fileVO.setUploadTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(fileStatus.getModificationTime()))); fileVOList.add(fileVO); } } catch (IOException e) { e.printStackTrace(); } PageInfo<FileVO> pageInfo = new PageInfo<>(fileVOList, pageNum, pageSize); return ResultVO.success(pageInfo); } // 上传文件 @PostMapping("/upload") @ResponseBody public ResultVO<?> uploadFile(@RequestParam("file") MultipartFile file) { try { FSDataOutputStream outputStream = fileSystem.create(new Path("/" + file.getOriginalFilename())); IOUtils.copyBytes(file.getInputStream(), outputStream, 4096, true); return ResultVO.success(); } catch (IOException e) { e.printStackTrace(); return ResultVO.error("上传文件失败!"); } } // 删除文件 @PostMapping("/delete") @ResponseBody public ResultVO<?> deleteFile(@RequestParam("fileIds") String fileIds) { String[] fileIdArray = fileIds.split(","); for (String fileId : fileIdArray) { try { fileSystem.delete(new Path("/" + fileId), false); } catch (IOException e) { e.printStackTrace(); return ResultVO.error("删除文件失败!"); } } return ResultVO.success(); } // 下载文件 @GetMapping("/download") public void downloadFile(@RequestParam("fileId") String fileId, HttpServletResponse response) { try { FSDataInputStream inputStream = fileSystem.open(new Path("/" + fileId)); response.setHeader("Content-Disposition", "attachment; filename=" + fileId); IOUtils.copyBytes(inputStream, response.getOutputStream(), 4096, true); } catch (IOException e) { e.printStackTrace(); } } } ``` 其中,`FileVO` 类用于封装文件信息,`ResultVO` 类用于统一接口返回格式,`PageInfo` 类用于封装分页信息。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值