django 没有读取 javascript 表单数据文件

django is not reading javascript form-data files

所以当我尝试将文件发送到 Django 服务器时,它引发了大量错误:

Traceback (most recent call last):
  File "C:\Users\TM\AppData\Local\Programs\Python\Python39\lib\site-packages\PIL\Image.py", line 2972, in open
    fp.seek(0)
AttributeError: 'NoneType' object has no attribute 'seek'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\TM\AppData\Local\Programs\Python\Python39\lib\site-packages\asgiref\sync.py", line 482, in thread_handler
    raise exc_info[1]
  File "C:\Users\TM\AppData\Local\Programs\Python\Python39\lib\site-packages\django\core\handlers\exception.py", line 38, in inner
    response = await get_response(request)
  File "C:\Users\TM\AppData\Local\Programs\Python\Python39\lib\site-packages\django\core\handlers\base.py", line 233, in _get_response_async
    response = await wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:\Users\TM\AppData\Local\Programs\Python\Python39\lib\site-packages\asgiref\sync.py", line 444, in __call__
    ret = await asyncio.wait_for(future, timeout=None)
  File "C:\Users\TM\AppData\Local\Programs\Python\Python39\lib\asyncio\tasks.py", line 442, in wait_for
    return await fut
  File "C:\Users\TM\AppData\Local\Programs\Python\Python39\lib\concurrent\futures\thread.py", line 52, in run
    result = self.fn(*self.args, **self.kwargs)
  File "C:\Users\TM\AppData\Local\Programs\Python\Python39\lib\site-packages\asgiref\sync.py", line 486, in thread_handler
    return func(*args, **kwargs)
  File "C:\Users\TM\AppData\Local\Programs\Python\Python39\lib\site-packages\django\views\decorators\csrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
  File "C:\Users\TM\سطح المكتب\New folder\web\views.py", line 86, in makeAccountApi
    IMG=RESIZE(Image)
  File "C:\Users\TM\سطح المكتب\New folder\web\helpers.py", line 110, in RESIZE
    im = Image.open(Img)
  File "C:\Users\TM\AppData\Local\Programs\Python\Python39\lib\site-packages\PIL\Image.py", line 2974, in open
    fp = io.BytesIO(fp.read())
AttributeError: 'NoneType' object has no attribute 'read'

当我 print request.body 并请求文件并请求 POST 它打印:

b'[object FormData]'
<MultiValueDict: {}>
<QueryDict: {}>

当我打印文件时 console.log:

C:\fakepath\download.jpg

然后是 console.log:

request.js:62 [Deprecation] Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.
PostData @ request.js:62
sumbit @ login.js:8
(anonymous) @ VM103:1
request.js:64 POST http://127.0.0.1:8000/api/makeuser/dsa/ 400 (Bad Request)

而且我也没有制作按钮来触发该功能,所以我从控制台触发该功能 在此处输入图片描述

enter image description here

------------代码部分: 对于请求函数:

function PostData(url, method="get", data="") {

    url=url.toString();
    method=method.toString();
    data=data.toString();

//CHECK CSRF-Token

    function getCookie(name) {
    var cookieValue = null;
    if (document.cookie && document.cookie !== '') {
        var cookies = document.cookie.split(';');
        for (var i = 0; i < cookies.length; i++) {
            var cookie = cookies[i].trim();
            // Does this cookie string begin with the name we want?
            if (cookie.substring(0, name.length + 1) === (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}

//Check if there is a hidden csrf-input-field, if so, get the value

try {
    var csrffield = document.getElementsByTagName("input");

    var l = csrffield.length;
    var i=0;

while (true) {
    if (i > l) {
        break;
    }

    if (csrffield[i].name.toLowerCase().includes("csrf") == true) {
        csrftoken=csrffield[i].value;
        break;
    }
    i++;
}}
catch (err) {
    var csrftoken = getCookie('csrftoken');


}

    var req = new XMLHttpRequest();

    if (method == "get" || method == "GET" || method == "Get") {

        req.open("GET", url, false);
        req.send();
    if (req.status == 200) {
        return req.responseText;
}}

if (method == "post" || method == "POST" || method == "Post") {

    req.open("POST", url, false);
    req.setRequestHeader('Content-Type','multipart/form-data')
    req.send(data);



    return req.responseText;
}}

求和函数:

function sumbit() { 
    var errorhandler = document.getElementById("Error")
    var user = document.getElementById("user").value;
    var file = document.getElementById("pfp").value;
    console.log(file,user)
    var formData = new FormData();   
    formData.append("Image",file);
    request = PostData(`http://127.0.0.1:8000/api/makeuser/${user}/`,'POST',formData)
    if(request == "555") { 
        errorhandler.innerHTML = "Image or User required to make account";
    }
    else if(request=="556") { 
        errorhandler.innerHTML = "User already in use";

    }
    else if(request=="Made") {
        window.location= "http://127.0.0.1:8000/joinroom/"

    }else { 
        errorhandler.innerHTML = "Unkown error";


    }



}

这里是完整版的 views.py:

from django.http.response import HttpResponse
from django.shortcuts import render
from .models import rooms,accounts



from .helpers import RESIZE,file_size,BasicToken #Importing helpers functions 



from django.utils.crypto import get_random_string
from django.views.decorators.csrf import csrf_exempt









# Create your views here.
def login(request):
    return render(request,'loginpage.html')

def makeroom(request):
    return render(request,'makeroom.html')


def joinroom(request):
    return render(request,'joinroom.html')


def chatroom(request,ID):
    return render(request,'chatroom.html')


#Api

#this Api makes chatting rooms 
def makeroomApi(request):
    Name = 'dd'
    namegenerated=False

    #Here the ID generated
    while(namegenerated==False) : 
            Name  = get_random_string(length=6)   


            try :
                rooms.objects.get(roomid=Name)
                namegenerated=False                
            except:
                namegenerated=True
                pass

            

    room = rooms(roomid=Name)
    room.save()
    return HttpResponse(Name)


#this Api makes chatting rooms 
@csrf_exempt
def makeAccountApi(request,User):
    print(request.body)
    print(request.FILES)
    ## 555 error means that theres data we need that is not in our request
    ## 12 means that method is not post
    ## 556 mean that user is already available
    ## 212 means that file's size is big
    try:
        if  User.isspace():
            print(User.isspace())
            print("555")
            return HttpResponse("555")
    except: 
            print("555")
            return HttpResponse("555")

    if request.method == 'POST':
        Image=request.FILES.get("Image")
        print(request.body)
        IMG=RESIZE(Image)
        token=BasicToken()
        if file_size(Image,2) == 1: 
            print('33')
            return HttpResponse("212")

        #Handling if the same user is used by some one 
        try:
            accounts.objects.get(user=User)
            print("user in use")
            return HttpResponse('556')
        except:
            #if the user is not available then save to database
            room = accounts(user=User,image=IMG,token=token)
            room.save()
        print("made")
        return HttpResponse('Made')
    else: 
        return HttpResponse("12")

这里是views.py的简化版本:

请求函数

@csrf_exempt
def makeuser(request,User):
    if request.method == 'POST':
        Image=request.FILES.get("Image")
        print(request.body)
        IMG=RESIZE(Image)
        token=BasicToken()
        if file_size(Image,2) == 1: 
            print('33')
            return HttpResponse("212")

        #Handling if the same user is used by some one 
        try:
            accounts.objects.get(user=User)
            print("user in use")
            return HttpResponse('556')
        except:
            #if the user is not available then save to database
            room = accounts(user=User,image=IMG,token=token)
            room.save()
        print("made")
        return HttpResponse('Made')

图像处理函数:

def RESIZE(Img):
    mask = Image.open(Mask).convert('L')
    im = Image.open(Img)
    outputimage = ImageOps.fit(im, mask.size, centering=(0.5, 0.5))
    outputimage.putalpha(mask)

    #Convering the image to django file so we can upload it to our database
    image_io = io.BytesIO()
    outputimage.save(image_io, format='png')
    outputimage = '{}.{}'.format('filename','.png')
    image = ContentFile(image_io.getvalue(), outputimage)
    return image

我的完整 HTML 代码:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <link rel="shortcut icon" type="image/x-icon" href="http://127.0.0.1:8000/files/Logo.ico" />


    <meta name="keywords" content="chat,chatting,roomchat,groupchat,group">
    <meta name="description" content="Free chatting website! 
    you can chat now with ur friends with our rooms chat service">
    <meta property="og:image" content="https://developer.mozilla.org/static/img/opengraph-logo.png">
    <meta property="og:description" content="Free chatting website! 
    you can chat now with ur friends with our rooms chat service">
    <meta property="og:title" content="Chatting">
    <style>
     @import url('https://fonts.googleapis.com/css2?family=Almarai:wght@300&display=swap');
     div {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
  min-height: 100vh;
}
    h1 { 
        font-family: "Almarai";


    }
    .inputimage {

 
        margin: 5px;
    font-size: larger;
    padding-left: 10%;
    }
    .inputuser{
        border: 0px;
    padding: 3px;
    border-bottom: 5px solid RGB(0,0,0,33%);
    font-size: 20px;
    font-family: "Almarai";
 
    }
    .inputuser:focus {
        font-size: 22px;
        outline: none;
    }
    .sumbitbutton {  
      margin:10px;
      color:black;
      background-color: transparent;
      border-color: black;
      border-style: solid;
      border-width: 2px;
      width: 17vh;
      min-width: 179px;
      font-size: 32px;
      border-radius: 20px;
      cursor: pointer;
    }
    .sumbitbutton:hover { 
      background-color:black;
      color:white;
    }

</style>
    <title>Login page</title>
  </head>
  <body>

    <div>
          <form action = "http://127.0.0.1:8000/api/makeuser/taha/" method = "POST">
            <h1 id="Error"></h1>
            <input type='text' id="user" autofocus placeholder="Username" class="inputuser">
            <h1>Your PFP</h1>
            <input type="file" id="pfp" alt="" class="inputimage"  accept=".jpg,.png">
            <input type="submit">
            </form>
        </div>


        <script type="text/javascript" src="http://127.0.0.1:8000/files/request.js"></script>
        <script type="text/javascript" src="http://127.0.0.1:8000/files/login.js"></script>

  </body>
</html>

不要将您的数据转换为字符串

url=url.toString();  // url is already a string, don't do this
method=method.toString(); // method is already a string, don't do this
data=data.toString();  // don't convert data to a string, if it needed to be a string it should have been passed as a string(It doesn't). Don't do this 

另外,不要为multipart/form-data设置content-type header,它会自动正确设置。
您正在使用同步 ajax,这就是您收到弃用警告的原因。这将导致糟糕的用户体验,尤其是在文件上传时。 如果你想保持代码的流动,你可以看看 async/await、Promises 和 Fetch API。