django+vue文件流传递docx文档(python-docx+postman测试文件下载+前端乱码解决)

django

用python-docx在本地先生成自己想要的文件,注意报错比如level=1没有这样的,需要把模板文件先设置一下标题级别,然后删了。

settings.py一些变化

INSTALLED_APPS = [
    'django.contrib.admin',  # 内置的后台管理系统
    'django.contrib.auth',  # 内置的用户认证系统
    'django.contrib.contenttypes',  # 记录项目中所有model元数据
    'django.contrib.sessions',  # session会话功能
    'django.contrib.messages',  # 消息提示功能
    'django.contrib.staticfiles',  # 查找静态资源路径
    'corsheaders', # 跨域设置
    'user'
]

MIDDLEWARE = [
    'corsheaders.middleware.CorsMiddleware', # 跨域设置,注意位置!
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    # 'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

# 设定文件的访问路径,如:访问http://127.0.0.1:8000/media/就可以获取文件
MEDIA_URL = '/media/'
# 设置文件的存储路径,全部存储在media目录下
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

urls.py新增

    path('question/download/word', views.DownloadQnaireToWord.as_view()),  # 导出为word文档

views.py

class DownloadQnaireToWord(View):
    base_file = MEDIA_ROOT + '\\user_survey_template\\template.docx' # 模板文件
    document = Document(base_file) # 生成的目标文件

    # 添加段落内容(文本内容,字体大小,字体颜色,字体粗细)
    def addParaText(self, text, size, color, underline, thickness):
        p = self.document.add_paragraph()  # 段落
        p.paragraph_format.line_spacing = 1.5
        text = p.add_run(text)
        # 判断字体是否加粗(1为不加粗)
        if thickness == 1:
            text.bold = False
        else:
            text.bold = True  # 加粗
        text.font.name = 'Times New Roman'
        text.font.size = Pt(size)
        text.font.color.rgb = color
        text.font.underline = underline

    # 添加标题
    def addHeadText(self, text, size):
        self.document._body.clear_content()  # 清空前面的内容
        title_ = self.document.add_heading(level=5)
        title_.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER  # 标题居中
        title_run = title_.add_run(text)  # 添加标题内容
        title_run.font.size = Pt(size)  # 设置标题字体大小
        title_run.font.color.rgb = RGBColor(0, 0, 0)  # 字体颜色

    # 删除非模板文件
    def delete_docx_file(self):
        filepath = MEDIA_ROOT + '\\user_surveys\\'
        if os.path.exists(filepath):
            files = os.listdir(filepath)
            for file in files:
                if file != "template.docx":
                    os.remove(os.path.join(filepath, file))

    # 流方式读取文件
    def read_file(self, file_name, size):
        with open(file_name, mode='rb') as fp:
            while True:
                c = fp.read(size)
                if c:
                    yield c
                else:
                    break

    def post(self, request):
        self.delete_docx_file()  # 收到请求后先把上次请求导出时本地生成的docx文件删除
        # 文件处理开始,这里有简略
        self.addHeadText(x,x)  # 文档名
        self.addParaText('', 11, RGBColor(0, 0, 0), False, 1) #文件段落
        filepath = MEDIA_ROOT + '\\user_surveys\\'  # 自己的路径
        filename = str(survey.sID) + '-' + survey.sName + '.docx' #自己定义的文件名
        self.document.save(filepath + filename) #保存到本地,至此本地文件夹能看到生成的文件
		# 文件处理结束,返回文件流
        response = StreamingHttpResponse(self.read_file(os.path.join(filepath, filename), 512))
        response[
            'Content-Type'] = 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
        response['Content-Disposition'] = "attachment; filename*=utf-8''{}".format(escape_uri_path(filename))
        if response:
            return response
        else:
            return JsonResponse({'success': False, 'message': '导出失败,请联系管理员解决!'},json_dumps_params={'ensure_ascii': False})

后端postman测试文件下载无误

post请求时选择send and download,会弹出文件资源管理器,注意把后缀加上,默认只有respoonse的
在这里插入图片描述
在这里插入图片描述

vue

下载的按钮

                    <el-button
                      type="success"
                      icon="el-icon-upload2"
                      circle
                      @click="handleOutWord(item)"
                    ></el-button>

关联的函数

    async handleOutWord(item) {
      var id = item.sID;
      var sName = item.sName;
      await new Promise((resolve) => {
        this.$http
          .post("/question/download/word", JSON.stringify({ sID: id }), {
            responseType: "blob",
          })  // 乱码一定要加 responseType: "blob"
          .then((res) => {
            console.log(res,'看一下res是啥');
            const data = res.data;
            const url = window.URL.createObjectURL(
              new Blob([data], {
                type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
              })
            );
            console.log(url,'看一下url是啥')
            const a = document.createElement("a");
            document.body.appendChild(a);
            a.style.display = "none";
            a.href = url;
            let filename=sName;
            a.download = filename;
            console.log(filename)
            a.click();
            document.body.removeChild(a);
            window.URL.revokeObjectURL(url);
          });
        resolve();
      });
    },

main.js中关于axios的一些设置

在这里插入图片描述

部署后

项目部署在阿里云服务器上时,起初提示500(Internet Server Error)原因是目录或者文件的权限没有开启,不能创建、编辑或者删除文件。用chmod 777 文件名或文件夹名开启即可。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值