Django+Vue上传文件相关操作

同名文件覆盖及删除后台数据同时删除本地文件

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)  # 关联信号

完成同时删除本地文件。

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值