基于Django+Vue实现文件上传下载

一、背景

公司使用的是testlink去维护测试用例,但是因为一些客观原因导致testlink编写测试用例不方便、不易用。同时,testlink的导入只支持xml文件,平常都是大家在excel内编写,然后将excel转为xml,再将xml文件导入到testlink里面。本文只分享上传下载的功能,文件格式内容转换涉及到业务内容就不分享啦。

二、详细信息

  • 仅支持上传xls/xlsx文件,如果不是则抛出错误提示

  • 支持拖拽上传或点击上传,一次只能上传单个文件

  • 上传excel后, 右侧展示其所有sheet的checkbox,选中下载

效果演示:

功能演示

三、上传文件部分

页面展示部分

select your Excel here

将文件拖到此处,或点击上传
只能上传xlsx/xls文件,且不超过5M
请求接口鉴权

因为上传接口需要鉴权,所以需要在发送网络请求的时候携带认证信息:

 data() {
    return {
      headers: {
        'Authorization': "Token " + this.$auth.token
      }
    }
  },
 mounted() {
     let backURLl
     backURLl = window.VUE_APP_URL.backURL    //上传接口
     this.backUrl=backURLl + "/api/v1/AvatarUpload/"
      },
文件上传校验

避免程序出错,需要限制上传的文件类型和大小,在此实现:

export default{  
  methods: {
    // excel表上传
    handleBefore(file) {
        // 文件类型
      console.log(`上传前校验---`, file)
      const isType = file.type === 'application/vnd.ms-excel'
      const isTypeComputer = file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
      const fileType = isType || isTypeComputer
      if (!fileType) {
        this.$message.error('上传文件只能是xls/xlsx格式!')
      }
      // 文件大小限制为5M
      const fileLimit = file.size / 1024 / 1024 < 5
      if (!fileLimit) {
        this.$message.error('上传文件大小不超过5M!')
      }
      return fileType && fileLimit
    },
}
}
解析内存文件

常常在使用xlrd模块时,一般都是解析本地的某个实质性、物理的文件。而此处不一样,从前端传送过来,我并不想将其落到磁盘里面,于是直接在内存中直接进行解析文件(InMemoryUploadedFile)

使用方法:

files = request.FILES.get('file')
book = xlrd.open_workbook(filename=None, file_contents=files.read())

整体响应如下:

class AvatarUpload(APIView):
    authentication_classes = (TokenAuthentication,)  # token认证
    permission_classes = (IsAuthenticated,)  # IsAuthenticated 仅通过认证的用户

    def post(self, request):
        '''
        :param request:
        :return:  a list of sheet name
        '''
        files = request.FILES.get('file')
        book = xlrd.open_workbook(filename=None, file_contents=files.read())
        sheetnames = book.sheet_names()
        filename = files.name
        ExcelToXml(book, filename, sheetnames).to_xml()
        return Response(sheetnames)

四、下载文件部分

上传文件之后,能够获得其的sheet页,在页面上勾选,点击下载即可。

页面展示部分
 

There is sheets of Excel!

 
      {{city}}     点击下载xml

当勾选或取消勾选选项的时候,需要实时处理数据,保证向后端提供的参数正确:

methods:{
    handleCheckedCitiesChange(value) {
      this.sheetnames=value
      let checkedCount = value.length;
      this.isIndeterminate = checkedCount > 0 && checkedCount < this.cities.length;
    },
    async getXML(){
      this.sheetnames.forEach(item=>{
      this.$http.getXML(item).then(res=>{
        let url = this.backUrl +  "?sheetname=" + item
        window.open(url)
      }).catch(err=>{
        this.$message.error("something not found")
      })
    })
}
FileResponse下载文件

在后端下载功能则比较简单了,只需要从指定的目录找到对应的文件,同时在response中设置正确Content-Type、Content-Disposition即可

顺便简单描述一下:

Content-Type:发送端(客户端|服务器)发送的实体的数据类型,常见的text/html,application/json

Content-Disposition:把请求所得的内容存为一个文件的时候提供一个默认的文件名。

实际使用如下:

def get(self, request):
    '''
    :param request:根据参数确认是下载xml文件 还是 demo模板
    :return: a file
    '''
    BASE_DIR = Path(__file__).resolve().parent.parent
    xml_ROOT = os.path.join(BASE_DIR, 'testlink')
    sheetname = request.query_params.get("sheetname")
    demo = "demo.xlsx"
    if sheetname:
        sheetname = sheetname + ".xml"
        filepath = os.path.join(xml_ROOT, sheetname)
    else:
        filepath = os.path.join(xml_ROOT, demo)
    filename = sheetname if sheetname else demo
    if os.path.exists(filepath):
        response = FileResponse(open(filepath, 'rb'))  # 生成文件对象application/msword  application/octet-stream
        response['Content-Type'] = 'application/octet-stream'
        response['Content-Disposition'] = 'attachment;filename ="%s"' % (
            filename.encode('utf-8').decode('ISO-8859-1'))
        return response
    else:
        return Response({"notFound": sheetname}, status=400)

你可能感兴趣的:(DRF,+,VUE,自动化测试平台,django,后端,vue.js,elementui)