vue.js

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript类库 > vue.js > Vue  WebApi上传下载

Vue + WebApi 实现上传下载功能(完整示例)

作者:_tiddler

本文通过实例代码介绍Vue + WebApi实现上传下载功能,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧

vue上传:

UI:

  <el-button
        size="mini"
        type="text"
        icon="el-icon-document-add"
        @click="handleUpload()"
        >上传
      </el-button>
      <el-dialog
        :title="Title"
        :visible.sync="open"
        width="600px"
        append-to-body
        :close-on-click-modal="false"
      >
        <el-upload
          ref="upload"
          :limit="1"
          :on-remove="handleRemove"
          :on-error="onError"
          :file-list="fileList"
          :auto-upload="false"
          :http-request="customUpload"
          action="http://localhost:5000/api/Resource/AddResource"
          class="upload-demo"
        >
          <el-button slot="trigger" size="small" type="primary"
            >选取文件</el-button
          >
          <el-button
            style="margin-left: 10px;"
            size="small"
            type="success"
            @click="submitUpload"
            >上传到服务器</el-button
          >
          <div slot="tip" class="el-upload__tip">
            支持上传 {{ strRebuild(fileType) }} 格式,且不超过 {{ fileSize }}M
          </div>
        </el-upload>
      </el-dialog>

点击按钮触发方法,open为true 上传弹窗出现:

handleUpload() {
      this.title = "XXXX";
      this.open = true;
    },

选择文件后,点击上传到服务器,触发以下方法:

 customUpload(file) {
      console.debug("进入上传方法");
      const param = new FormData();
      param.append("files", file.file);
      console.log("上传文件:", file);
      console.log("FormData:", param);
      uploadFile(param);
      setTimeout(() => {
        this.open = false;
        message("success", "上传成功");
        this.$refs.upload.clearFiles();
        this.fileList = [];
      }, 1500);
    },

其中触发封装的请求方法:

export async function uploadFile(file) {
  try {
    console.log("上传资源参数:", file);
    // 尝试不同的路径格式
    
    const response = await request.post("/Resource/UploadFile", file);

    console.log("API响应:", response);
    return response;
  } catch (error) {
    console.error("获取文章列表失败:", error);
    throw error;
  }
}

.Net 后端Api:

/// <summary>
/// 上传客户端文件并保存
/// </summary>
[HttpPost("UploadFile")]
public async Task<IActionResult> UploadFile(IFormFileCollection files)
{
    foreach (var file in files)
    {
        // 判断文件是否有内容
        if (file.Length == 0)
        {
            Console.WriteLine("该文件无任何内容!!!");
            continue;
        }
        // 获取附件原名
        string fileName = file.FileName;
        // 如果是获取的含有路径的文件名,那么截取掉多余的,只剩下文件名和后缀名
        if (fileName.Contains("\\"))
        {
            int index = fileName.LastIndexOf("\\");
            fileName = fileName.Substring(index + 1);
        }
        // 判断单个文件大于1M
        long fileSize = file.Length;
        if (fileSize > 1024 * 1024)
        {
            Console.WriteLine($"文件大小为(单位字节):{fileSize}");
            Console.WriteLine("该文件大于1M");
        }
        // 构建完整保存路径
        var fullPath = Path.Combine(_webHostEnvironment.WebRootPath, $"Resources/{Guid.NewGuid()}{fileName}");
        var directory = Path.Combine(_webHostEnvironment.WebRootPath, $"Resources");
        if (!Directory.Exists(directory))
        {
            Directory.CreateDirectory(directory);
        }
        try
        {
            // 将文件保存到指定位置
            using (var stream = new FileStream(fullPath, FileMode.Create))
            {
                await file.CopyToAsync(stream);
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
            return StatusCode(500, new { message = "文件上传失败", error = e.Message });
        }
    }
    return Ok(new { success = true, message = "上传成功" });
}

可以使用IFormFileCollection 接口类型对接前端的FormData类型。通过FileStream 类传输文件。

因为_webHostEnvironment.WebRootPath对应wwwroot,所以文件会保存在wwwroot目录下。

其实应该有对应的表格。上传的文件信息会保存在数据库里,这里图方便就没写。

下载:

下载的方法有很多种,这里展示Fetch下载:

 downloadFile(fileName) {
      const fileUrl = this.$baseURL + "\\Resources\\" + fileName; // 文件的URL地址
      fetch(fileUrl)
        .then((response) => response.blob())
        .then((blob) => {
          const url = window.URL.createObjectURL(blob);
          const link = document.createElement("a");
          link.href = url;
          link.setAttribute("download", fileName);
          document.body.appendChild(link);
          link.click();
        })
        .catch((error) => {
          console.error(error);
        });
    },

按钮调用:

<button @click="downloadFile('test.png')">下载文件2</button>

在方法里直接拼接了图片(其他文件类似)的url,会在浏览器中下载以下图片:

完整vue代码:

<template>
  <div class="front-container">
    <div>
      <h2>往昔峥嵘</h2>
      <el-button
        size="mini"
        type="text"
        icon="el-icon-document-add"
        @click="handleUpload()"
        >上传
      </el-button>
      <el-dialog
        :title="Title"
        :visible.sync="open"
        width="600px"
        append-to-body
        :close-on-click-modal="false"
      >
        <el-upload
          ref="upload"
          :limit="1"
          :on-remove="handleRemove"
          :on-error="onError"
          :file-list="fileList"
          :auto-upload="false"
          :http-request="customUpload"
          action="http://localhost:5000/api/Resource/AddResource"
          class="upload-demo"
        >
          <el-button slot="trigger" size="small" type="primary"
            >选取文件</el-button
          >
          <el-button
            style="margin-left: 10px;"
            size="small"
            type="success"
            @click="submitUpload"
            >上传到服务器</el-button
          >
          <div slot="tip" class="el-upload__tip">
            支持上传 {{ strRebuild(fileType) }} 格式,且不超过 {{ fileSize }}M
          </div>
        </el-upload>
      </el-dialog>
      <button @click="downloadFile('test.png')">下载文件2</button>
    </div>
    <div class="blog-list">
      <BlogCard
        v-for="blog in blogs"
        :key="blog.id"
        :blog="blog"
        @view-detail="handleViewDetail"
      />
    </div>
  </div>
</template>
<script>
import { lastSubstring, strRebuildEx } from "@/utils/util";
import { message } from "@/utils/message";
import { blogList } from "../mock/blogData.ts";
import { uploadFile } from "@/api/resources";
import BlogCard from "@/components/BlogCard.vue";
export default {
  name: "BlogList",
  components: {
    BlogCard,
  },
  data() {
    return {
      Title: "上传组件",
      open: false,
      blogs: blogList,
      // 附件列表
      fileList: [],
      // 允许的文件类型,可依据实际需求增加格式
      fileType: [
        "xls",
        "xlsx",
        "pdf",
        "doc",
        "docx",
        "txt",
        "jpg",
        "png",
        "jpeg",
        "zip",
      ],
      //fileType: ["pdf", "doc", "zip"],
      // 运行上传文件大小,单位 M
      fileSize: 10,
    };
  },
  methods: {
    handleViewDetail(blog) {
      console.log("查看博客详情:", blog);
    },
    // downloadFile(fileName) {
    //   const fileUrl = this.$baseURL + "\\Resources\\" + fileName; // 文件的URL地址
    //   console.debug(fileUrl);
    //   const link = document.createElement("a");
    //   link.href = fileUrl;
    //   link.setAttribute("download", fileName);
    //   link.click();
    // },
    downloadFile(fileName) {
      const fileUrl = this.$baseURL + "\\Resources\\" + fileName; // 文件的URL地址
      fetch(fileUrl)
        .then((response) => response.blob())
        .then((blob) => {
          const url = window.URL.createObjectURL(blob);
          const link = document.createElement("a");
          link.href = url;
          link.setAttribute("download", fileName);
          document.body.appendChild(link);
          link.click();
        })
        .catch((error) => {
          console.error(error);
        });
    },
    handleUpload() {
      this.title = "XXXX";
      this.open = true;
    },
    // 清空表单
    clear() {
      // 清空附件
      this.$refs.upload.clearFiles();
    },
    // 附件检查
    // 检查附件是否属于可上传类型
    // 检查附件是否超过限制大小
    checkFile() {
      var flag = true;
      var tip = "";
      var files = this.$refs.upload.uploadFiles;
      files.forEach((item) => {
        // 文件过大
        if (item.size > this.fileSize * 1024 * 1024) {
          flag = false;
          tip = " 文件超过" + this.fileSize + "M";
        }
        // 文件类型不属于可上传的类型
        if (!this.fileType.includes(lastSubstring(item.name, "."))) {
          flag = false;
          tip = " 文件类型不可上传";
          this.clientOpen = false;
        }
      });
      if (!flag) {
        message("error", tip);
      }
      return flag;
    },
    // 提交附件
    submitUpload() {
      if (this.checkFile()) {
        console.log("上传附件...");
        this.$refs.upload.submit();
      } else {
        console.log("取消上传");
      }
    },
    // 自定义文件上传方法
    customUpload(file) {
      console.debug("进入上传方法");
      const param = new FormData();
      param.append("files", file.file);
      // 模拟上传成功
      console.log("上传文件:", file);
      console.log("FormData:", param);
      uploadFile(param);
      // 模拟API调用
      setTimeout(() => {
        this.open = false;
        message("success", "上传成功");
        this.$refs.upload.clearFiles();
        this.fileList = [];
      }, 1500);
    },
    // 移除附件
    handleRemove(file, fileList) {
      console.log("移除附件...");
    },
    // 附件上传失败,打印下失败原因
    onError(err) {
      message("error", "附件上传失败");
      console.log(err);
    },
    strRebuild(arr) {
      strRebuildEx(arr, ",");
    },
  },
};
</script>
<style>
.navbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  background-color: #2c3e50;
  padding: 1rem 2rem;
}
.nav-brand {
  color: white;
  font-size: 1.2rem;
  font-weight: bold;
}
.nav-links {
  display: flex;
  align-items: center;
  gap: 0;
}
.nav-link {
  color: white;
  text-decoration: none;
  padding: 0.5rem 1rem;
  border-radius: 4px;
  transition: all 0.3s ease;
  white-space: nowrap;
}
.nav-link:hover {
  background-color: #34495e;
  transform: translateY(-1px);
}
.router-link-active {
  background-color: #42b883;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
}
.separator {
  width: 1px;
  height: 20px;
  background-color: rgba(255, 255, 255, 0.3);
  margin: 0 0.5rem;
}
.el-row {
  margin-bottom: 20px;
}
.el-col {
  border-radius: 4px;
}
.bg-purple-dark {
  background: #99a9bf;
}
.bg-purple {
  background: #d3dce6;
}
.bg-purple-light {
  background: #e5e9f2;
}
.grid-content {
  border-radius: 4px;
  min-height: 36px;
}
.row-bg {
  padding: 10px 0;
  background-color: #f9fafc;
}
.viewmore-row {
  float: right;
  background: #12b7de;
  color: #fff;
  border-radius: 3px;
  padding: 0px 10px;
  height: 30px;
}
.bg-purple {
  background: #eaeaea;
  -webkit-animation: loading 1s ease-in-out infinite;
  animation: loading 1s ease-in-out infinite;
}
@keyframes loading {
  0% {
    width: 90%;
  }
  50% {
    width: 100%;
  }
  to {
    width: 90%;
  }
}
[v-cloak] {
  display: none !important;
}
</style>

根据自己需要把其中报错,不相干的代码删减掉。

到此这篇关于Vue + WebApi 实现上传下载功能的文章就介绍到这了,更多相关Vue WebApi上传下载内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文