Django 上传图片和下载图片

本文详细介绍Django框架下文件上传及下载的两种主要模式:通用万精油模式和使用框架模式。涵盖上传流程、数据库存储策略、文件路径管理及下载功能实现。

参考文章:
https://www.zhangshengrong.com/p/Z9a28xMkXV/

项目目录结构:
在这里插入图片描述

上传文件:

1、通用万精油模式:

settings 同级目录 urls:

from django.contrib import admin
from django.conf.urls import url,include
from middle import views

urlpatterns = [
    url('admin/', admin.site.urls),
    url(r'^middle/', include('middle.urls',namespace='middle')),
]

middle.urls:

from django.conf.urls import url
from middle import views

urlpatterns = [
    url(r'^uploadfile', views.upload_file, name='upload_file'),
    ]

middle.views:

def upload_file(request):
    if request.method == 'GET':
        return render(request,'upload.html')
    elif request.method == 'POST':
        icon = request.FILES.get("icon")

        with open("D:\project\django_introduction\static\img/1.jpg", "wb") as f:
            for part in icon.chunks():
                f.write(part)

    return HttpResponse("文件上传成功")

templates.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>文件上传</title>
</head>
<body>

<form action="{% url 'middle:upload_file' %}" method="post" enctype="multipart/form-data">

    {% csrf_token %}

    <span>文件:</span>
    <input type="file" name="icon">

    <br>
    <input type="submit" value="上传" >
    
</form>
</body>
</html>

2、使用框架模式:

settings:

# 新增
MEDIA_ROOT = os.path.join(BASE_DIR,'static/upload')

middle.models:

from django.db import models

class UserModel(models.Model):
    u_name = models.CharField(max_length=16)
    # upload_to 相对路径  相对于的是MEDIA_ROOT 媒体根目录
    u_icon = models.ImageField(upload_to='icons')

# 记得!!! 
# python manage.py makemigrations
# python manage.py migrate

middle.views:

def image_field(request):
    if request.method == 'GET':
        return render(request, 'image_field.html')
    elif request.method == 'POST':
        username = request.POST.get('username')
        icon = request.FILES.get('icon')

        user = UserModel()

        user.u_username = username
        user.u_icon = icon
        user.save()

    return HttpResponse("上传成功%d"%user.id)

# user.  后面会有其他方法,可以打印出来看

templates.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
        <form action="{% url 'middle:image_field' %}" method="post" enctype="multipart/form-data">
            {% csrf_token %}
            <span>用户名:</span><input type="text" name="username" placeholder="请输入用户名">
            <br>
            <span>头像:</span><input type="file" name="icon">
            <br>
            <button>上传</button>
        </form>
</body>
</html>

上传图片之后,数据库数据格式,这里的 icons 就是模型中相对路径:

在这里插入图片描述

根据用户名获取图片:

middle.views:

def mine(request):

    username = request.GET.get('username')

    user = UserModel.objects.get(u_username=username)

    icon_url = "/static/upload/" + user.u_icon.url

    data = {"username": username,"icon_url": icon_url}

    print(data)

    return render(request,'mine.html',context=data)

templates.mine:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Mine</title>
</head>
<body>

<h3>{{ username }}</h3>
<img src="{{ icon_url }}" alt="{{ username }}">

</body>
</html>

发现问题:

  • 1、上传的图都在一个文件夹下,不便于管理
  • 2、容易出现文件重名

解决问题:

middle.models:

from django.db import models
import uuid
import os

def upload_to(instance, filename):
    # 对文件进行重命名
    filename = '{}.{}'.format(uuid.uuid4().hex[:10], filename.split('.')[-1])
    return '/'.join([instance.u_username, filename])

class UserModel(models.Model):
    u_username = models.CharField(max_length=16)
    # upload_to 相对路径  相对于的是MEDIA_ROOT 媒体根目录
    u_icon = models.ImageField(upload_to=upload_to)

  • return ‘/’.join([instance.u_username, filename])
  • return 出去的就是文件夹了
  • 但是,之前我们获取的时候是根据 username 获取,现在不行了,只能根据id来获取了

views 修改传参:

在这里插入图片描述
html 修改参数:

在这里插入图片描述


下载文件:

# 下载图片/文件
def download(request):
    if request.method == 'GET':
        try:
            # path = request.GET.get('path')
            path = 'staticfiles/IDcardImg/1584431403.jpg'
            with open(path,'rb') as f:
                file = f.read()
            response = HttpResponse(file)
            # file_name下载下来保存的文件名字
            file_name = path.split('/')[-1]
            response['Content-Type'] = 'application/octet-stream'
            response['Content-Disposition'] = 'attachment;filename={}'.format(file_name)
            return response
        except Exception as e:
            print('error:',e)
            return JsonResponse({'code':500,'msg':'服务端错误','error':'{}'.format(e)})

个人小记:万精油的上传,下载

上传文件:

# -*- coding:utf-8 -*- 
# author: LIUWENYU
# contact: 1091761664@qq.com
# datetime: 2020/5/21 14:26
# software: PyCharm
# describe: 上传

from django.http.response import JsonResponse,HttpResponse
import time
import os
from wuliu import settings

# 上传图片/文件
def upload(request):
    if request.method == "POST":
        try:
            # 接收文件
            file = request.FILES['file']  # 上传的文件
            folder = request.POST['folder']  # 文件夹
            # print('folder:',folder)
			
			# 判断是否有 file 和 folder
            if not file and not folder:
                return JsonResponse({'code':400,'msg':'缺少参数'})

            # 限制文件大小
            if file.size > 10485760:
                return JsonResponse({'code':400,'msg':'请上传10MB以内的文件'})

            # 设置允许上传的文件格式
            ALLOW_EXTENSIONS = ['png', 'jpg', 'jpeg']

            # 文件名
            filename = str(time.time()).split(".")[0] + '.' + file.name.split(".")[-1]

            # 图片路径
            path = settings.BASE_DIR + '/static/' + folder + '/'

            # 判断文件格式
            if file.name.rsplit('.',1)[1].lower() in ALLOW_EXTENSIONS:
                # 假如文件夹不存在,创建文件夹
                if not os.path.exists(path):
                    os.makedirs(path)
            else:
                return JsonResponse({"code":400,'msg':'文件格式错误,请上传 png, jpg, jpeg'})
            # print('path:', path)
            # print('folder:',folder)

            with open(path + filename, 'wb') as f:
                # data = file.file.read()  # 文件字节流数据 从文件中读取整个上传的数据。小心整个方法:如果这个文件很大,你把它读到内存中会弄慢你的系统。
                # f.write(data)

                for buf in file.chunks(): # 如果上传的文件足够大需要分块就返回真。默认的这个值是2.5M,当然这个值是可以调节的
                    f.write(buf)

            url = '/' + folder + '/' + filename
            return JsonResponse({'code': 0, 'msg': '上传成功', 'url': url})
        except Exception as e:
            print('error:', e)
            return JsonResponse({'code': 500, 'msg':'服务端错误','error':'{}'.format(e)})

下载文件:

import os
from django.http.response import JsonResponse,HttpResponse
from django.utils.encoding import escape_uri_path

# 下载图片/文件
def download(path):
        try:
            path = path
            if not os.path.exists(path):
                return JsonResponse({'code':400,'msg':'文件不存在'},json_dumps_params={'ensure_ascii':False})
            print('path:',path)
            # path = 'staticfiles/IDcardImg/1584431403.jpg'
            with open(path,'rb') as f:
                file = f.read()
            response = HttpResponse(file)
            # file_name下载下来保存的文件名字
            file_name = path.split('/')[-1]
            print('file_name:',file_name)
            response['Content-Type'] = 'application/octet-stream'
            response['Content-Disposition'] = "attachment;filename={}".format(escape_uri_path(file_name))  # 处理中文乱码
            return response
        except Exception as e:
            print('error:',e)
            return JsonResponse({'code':500,'msg':'服务端错误','error':'{}'.format(e)})

可以修改参考,上面方法占内存:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值