Django+Vue 上传文件以及删除,覆盖文件

Vue+Django 处理上传的文件代码部分:
Vue部分:

            <el-upload
              ref="upload"
              :auto-upload='false' 
              :multiple='false'
              :before-upload="beforeUpload"
              :limit="1" 
              accept=".txt"
              action=""
              type="file"
              :http-request="chooseFile">
              <el-button class="reportFilebtn">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;选择文件</el-button>
            </el-upload>

method


    beforeUpload(file) {
      const fileSuffix = file.name.substring(file.name.lastIndexOf(".") + 1);
      const whiteList = ["txt"];
      if (whiteList.indexOf(fileSuffix) === -1) {
        this.$message.error('上传文件只能是txt格式');
        return false;
      }
    },

    chooseFile(file) {
      this.$refs.upload.clearFiles()
      this.file = file.file

      // if(JSON.stringify(file) != '{}'){
      var forms = new FormData()
      var configs = {
        headers:{'Content-Type':'multipart/form-data'}
      }
      forms.append('errList',this.uartlogForm.errList)
      forms.append('uartFile',this.file)

      this.logCheckStation = []
      uartLogTool(forms, configs).then(response => {
 	})   
},

Api.js

export const uartLogTool = (params)=>{
    return axios.post(`tool/uartParseErr`,params)
}

Django部分

def uartParseErr(request):

    if request.method == 'POST':
        response = {}
        
        uartFileData = request.FILES.get('uartFile', None)
        dutErrStr = request.POST.get('dutErrList','ERROR,Fail,Not Found').strip(',,')
        smokeyErrStr = request.POST.get('smokeyErrList','Not Found,All errors').strip(',,')

	#使用该方法缓存InMemoryFiles至Media/tmp文件夹,然后只需要把路径复制过去即可解析
        storageTempPath    = default_storage.save('tmp/{}'.format(uartFileData), ContentFile(uartFileData.read()))
        uartFilePath = os.path.join(settings.MEDIA_ROOT,storageTempPath)

        with open(uartFilePath,'r',encoding="utf-8") as file:
            log_data =  file.read()
	# 处理文件的代码省略


        try:
            response['uartData'] = dict_uart_log_data
            response['stationID'] = STATION_ID
            response['overlayVer'] = OVERLAY_VERSION
            response['msg'] = 'success'
            response['error_num'] = 0
        except Exception as e:
            #print(traceback.format_exc(limit=1))
            response['msg'] = str(e)
            response['error_num'] = 1

        #删除之前缓存的文件,避免内存臃肿
        os.remove(uartFilePath)
        return JsonResponse(response)

Django后台上传文件
1)Django上传文件配置,在settings配置:

# 配置上传文件目录
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, "media")

2)配置映射url

from django.views.static import serve
from django.conf import settings

urlpatterns = [
    ...,
    url(r'^media/(?P<path>.*)', serve, {"document_root": settings.MEDIA_ROOT}, name='media')
]

3)使用ivew上传组件实现上传头像 前端操作

<Upload
  ref="upload"
  type="drag"
  :before-upload="handleUpload"  // 上传之前的回调函数 返回true才表示成功
  :on-success="uploadSuccess"  // 上传成功的回调函数
  :on-error="uploadError"  // 错误回调函数
  :on-exceeded-size="handleMaxSize"  // 上传文件大小回调函数
  :max-size="2048" // 设置文件最大
  :data="data" // 其他上传数据
  :format="['jpg', 'png', 'jpeg']"  // 设置上传格式
  :on-format-error="handleFormatError2"  // 判断格式
  :action="api+'/api/uploadAvatar'"  // 上传的地方(接口)
>
  <div style="padding: 20px 0">
    <Icon type="ios-cloud-upload" size="52" style="color: #3399ff"></Icon>
    <p>Click or drag picture here to upload</p>
  </div>
</Upload>

handleUpload(file) {
  return true;
},
uploadSuccess(res) {
  //上传成功
  this.$Message.info(res.result.msg);
  if (res.result.code == 200) {
    this.$http
      .userLogin(this.author, this.pwd, this.getCookie("csrftoken"))
      .then(resp => {
        if (resp.result.code === "200") {
          var obj = {
            username: this.author,
            password: this.pwd,
            avatar: resp.result.avatar
          };
          sessionStorage.setItem("user", JSON.stringify(obj));
        }
      });
  }
  this.reload();
},
handleFormatError2() {
  this.$Message.error("文件格式不正确,请上传jpg、jpeg、png格式文件");
},
uploadError(error) {
  this.$Message.info(error);
},
handleMaxSize(file) {
  this.$Notice.warning({
    title: "超出文件大小限制",
    desc: "文件 " + file.name + " 太大,不能超过 2M。"
  });
},

4)后台接收前端文件操作

def upload_avatar(request):
    file = request.FILES.get('file', '')  # 获取文件 
    author = request.POST.get('author', '')  # 获取用户
    img_addr = '%s/person/%s' % (settings.MEDIA_ROOT, file.name)  # 指定文件上传路径及文件名
    # 写入文件
    with open(img_addr, 'wb') as f:
        for f_img in file.chunks():
            f.write(f_img)
    user = UserProfile.objects.get(Q(username=author) | Q(email=author))  # 获取用户对象
    user.portrait = 'person/'+file.name  # 修改用户头像
    user.save() # 保存
    data = {'code': '200', 'msg': '修改头像成功'}
    return JsonResponse({'result': data})

下载文件

from django.http import StreamingHttpResponse
import os
from django.utils.encoding import escape_uri_path  # 处理文件名文中文下载失败

def file_iterator(filename, chunk_size=512):
    with open(filename, 'rb') as f:
        while True:
            c = f.read(chunk_size)
            if c:
                yield c
            else:
                break

# 下载文件
def download_file_text(request, file_name):
    name = file_name.split('/')[-1]  # 显示在弹出对话框中的默认的下载文件名
    file_local = 'media/'+file_name  # 要下载的文件路径

    if not os.path.exists(file_local):
        return HttpResponse('File not found 404')

    response = StreamingHttpResponse(file_iterator(file_local))
    response['Content-Type'] = 'application/octet-stream'
    response['Content-Length'] = os.path.getsize(file_local)
    response['Content-Disposition'] = 'attachment;filename="{}"'.format(escape_uri_path(name))
    return response

同名文件覆盖
1)在app中新建stroage.py文件

from django.core.files.storage import FileSystemStorage
from django.conf import settings
import os

class OverwriteStorage(FileSystemStorage):
    def get_available_name(self, name, max_length=None):
        if self.exists(name):  # 上传文件同名则移除
            os.remove(os.path.join(settings.MEDIA_ROOT, name))
        return name

2)在models.py中引入

from interface.storage import OverwriteStorage

class DocumentDownload(models.Model):
    tag = models.ForeignKey(DocumentTag, related_name='tag_documents', verbose_name='文件类型', on_delete=models.CASCADE, null=True, blank=True)
    filename = models.CharField(max_length=100, verbose_name='文件名称')
    document = models.FileField(upload_to='documents', default='', verbose_name='文件', storage=OverwriteStorage())
    version = models.CharField(max_length=50, default='1.0.0', verbose_name='版本号')
    # equip_updated = models.BooleanField(default=True, verbose_name="根据设备可更新")
    updated = models.BooleanField(default=True, verbose_name="全局可更新文件")
    add_time = models.DateTimeField(verbose_name='添加时间', default=datetime.now)
    # 多对一(文件--类别)
    '''
    一个文件类型下面的所有文件:
    tag.tag_documents.all()
    '''
    
    class Meta:
        db_table = 'document_download'
        unique_together = ('tag', 'filename',)  # 联合唯一约束
        verbose_name = '文件管理'
        verbose_name_plural = verbose_name

    def __str__(self):
        return str(self.document)

这样就能在上传文件时同名文件覆盖。
删除数据库数据对应删除本地文件
1)在对应models文件

from django.db.models.signals import pre_delete
from django.dispatch.dispatcher import receiver

@receiver(pre_delete, sender=DocumentDownload)
def global_delete(sender, instance, **kwargs):
    # Pass false so FileField doesn't save the model.
    instance.document.delete(False)  # False 表示model不保存

pre_delete.connect(global_delete, sender=DocumentDownload)  # 关联信号
  • 26
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值