formulario de carga de forma
No tantos cosa, vistazo a un ejemplo:
código de front-end es importante.
<div>
<form action="" method="post" enctype="multipart/form-data"> {% csrf_token %} <input type="file" name="f1"> <input type="text" name="user"> <input type="submit" value="提交"> </form> </div>
En general, cuando un envío del formulario forma normal, encabezado de la solicitud CONTENT_TYPE: application/x-www-form-urlencoded
, y después los datos se transmiten en forma de pares de valores clave, el servidor desde request.POST
el valor, no hay duda, y CONTENT_TYPE: application/x-www-form-urlencoded
este tipo de codificación para la mayoría de los casos, todo lo muy bueno.
Y decir que el uso de la forma formulario para cargar un archivo, hay que decir unas palabras hacia arriba.
En un primer momento, el protocolo HTTP no está aspectos funcionales de carga de archivos hasta RFC1867 añadir esta funcionalidad al protocolo http. RFC1867 define en el curso de form
la etiqueta method
debe ser POST
, enctype = "multipart/form-data"
así <input type = "file">
.
Por lo tanto, cuando se utiliza el formulario de formulario para subir documentos, solicitud de cabecera content_type
es multipart/form-data
esta forma, por lo que tenemos que añadir una forma de etiqueta enctype="multipart/form-data
atributos para su identificación.
Si puede imprimir encabezado de solicitud para subir archivos, encontrará CONTENT_TYPE
es esto content_type:multipart/form-data; boundary=----WebKitFormBoundarylZZyJUkrgm6h34DU
, que boundary=----WebKitFormBoundarylZZyJUkrgm6h34DU
lo es?
En multipart/form-data
detrás boundary
y una cadena de caracteres, esto es el delimitador, una pila detrás de la cadena generada al azar, con el fin de prevenir la ocurrencia delimitador servidor de archivo de carga no puede identificar correctamente el principio del archivo. Eso delimitador y atenuarla?
Para la solicitud del poste cargue un archivo, no usamos el protocolo http original, por lo multipart / petición form-data se basa en la petición http post original método viene, entonces se dice que la diferencia entre esta nueva manera de enviar la solicitud:
- Solicitar una cabeza diferente, una solicitud de carga de archivos
contentType = multipart/form-data
es necesario, pero después no es, después de todo, no sólo se carguen archivos publican ~. - cuerpo de la solicitud diferente, es diferente se refiere aquí a la antigua (solicitud de carga) se debe utilizar entre cada delimitador de campo para separar la transmisión de contenido, como el contenido y archivos de texto necesitan separadas, de lo contrario el servidor no hay manera de la resolución de archivo normal, que por supuesto hay ningún delimitador posterior directamente
key:value
transmitida en forma ella.
Por supuesto, el curvado alrededor de unas pocas palabras no pueden explicar claramente, sabemos cómo utilizar en la línea.
Look vistas Vista de un proceso:
from django.shortcuts import render, redirect, HttpResponse
from django.db import transaction
def import_case(request, pk): """ 导入Excel数据,pk是所属项目的pk """ if request.method == 'POST': try: with transaction.atomic(): # 事物 # project_pk = request.POST.get("project_pk") # 数据库使用字段 excel = request.FILES.get('file_obj') book = xlrd.open_workbook(filename=None, file_contents=excel.read()) sheet = book.sheet_by_index(0) title = sheet.row_values(0) for row in range(1, sheet.nrows): print(sheet.row_values(row)) # 这里取出来每行的数据,就可以写入到数据库了 return HttpResponse('OK') except Exception as e: print(e) return render(request, 'import_case.html', {"project_pk": pk, "error": "上传文件类型有误,只支持 xls 和 xlsx 格式的 Excel文档"}) return render(request, 'import_case.html', {"project_pk": pk, "error": ""})
subir archivos ajax
La parte delantera del archivo:
<!DOCTYPE html>
<html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <!-- ajax上传文件开始 --> <div> {% csrf_token %} <input type="file" id="ajaxFile"> <button id="ajaxBtn">上传</button> </div> <!-- ajax上传文件结束 --> </body> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> <script> console.log($("[name='csrfmiddlewaretoken']").val()); $("#ajaxBtn").click(function () { // 首先,实例化一个formdata对象 var formData = new FormData(); // 然后使用formdata的append来添加数据,即获取文件对象 // var file_obj = $("#ajaxFile")[0].files[0]; // 使用jQuery获取文件对象 var file_obj = document.getElementById('ajaxFile').files[0]; // 使用dom也行 formData.append('f1', file_obj ); // 处理csrftoken formData.append("csrfmiddlewaretoken", $("[name='csrfmiddlewaretoken']").val()); // 也可以将其他的数据,以键值对的形式,添加到formData中 formData.append('user','张开'); $.ajax({ url: "/upload/", type: "POST", data: formData, processData:false, // contentType:false, success:function (dataMsg) { console.log(dataMsg); } }) }) </script> </html>
Ajax conjunto con el fin de evitar la falsa solicitud contentType jQuery cabeza content_type
opera, perdiendo así delimitador, el servidor de archivos no puede resolver correctamente.
En el uso de método jQuery $ .ajax () cuando el parámetro predeterminado processData a verdadero (que es un jQuery única), el valor predeterminado será el caso de la secuencia de datos transmitida a adaptarse aplicación tipo de contenido predeterminado / x-www-form -urlencoded
tiempo si desea no quieren enviar información a la necesidad de ajustar manualmente a false.
Echemos un vistazo en el back-end de views.py
cómo hacer frente a:
import xlrd
from django.shortcuts import render
from django.http import JsonResponse def upload(request): if request.is_ajax(): # print(request.META['CONTENT_TYPE']) # multipart/form-data; boundary=----WebKitFormBoundaryuXDgAwSKKIGnITam # print(request.POST) # <QueryDict: {'csrfmiddlewaretoken': ['mx1EBTtsOb0k96TUUW8XKbCGvK0Co3S6ZMlLvOuZOKAlO9nfhf6zol0V8KxRxbwT'], 'user': ['张开']}> # print(request.FILES) # <MultiValueDict: {'f1': [<InMemoryUploadedFile: 接口测试示例.xlsx (application/vnd.openxmlformats-officedocument.spreadsheetml.sheet)>]}> f1 = request.FILES.get('f1') print(f1) # 接口测试示例.xlsx book = xlrd.open_workbook(filename=None, file_contents=f1.read()) sheet = book.sheet_by_index(0) print(sheet.row_values(1)) # ['cnodejs项目', 'get /topics 主题首页', 'https://cnodejs.org/api/v1/topics', 'get', '', '{"success":true}'] return JsonResponse({"message": "upload successful"}) else: return render(request, 'upload.html')
OK, decir nada bueno, estaría terminado seco.
descargar
uso StreamingHttpResponse
vistas en el código principal:
from django.http import StreamingHttpResponse
def download(request): file=open('crm/models.py','rb') response =StreamingHttpResponse(file) response['Content-Type']='application/octet-stream' response['Content-Disposition']='attachment;filename="models.py"' return response
uso FileResponse
vistas en el código principal:
from django.http import FileResponse
def download(request): file=open('crm/models.py','rb') response =FileResponse(file) response['Content-Type']='application/octet-stream' response['Content-Disposition']='attachment;filename="models.py"' return response
Nombre de archivo no puede resolver los problemas en China
Si usted tiene cuidado de tratar, se encuentran dos formas de descargar lo anterior filename
no puede contener chino, entonces, ¿cómo se puede solucionar? Mirar hacia abajo!
from django.http import FileResponse
from django.utils.encoding import escape_uri_path # 导入这个家伙 def download(request): file=open('crm/models.py','rb') response =FileResponse(file) response['Content-Type']='application/octet-stream' response['Content-Disposition']='attachment;filename="{}.py"'.format(escape_uri_path("我是中文啦")) return response
No está resuelto! Perfecto! !
formulario de carga de forma
No tantos cosa, vistazo a un ejemplo:
código de front-end es importante.
<div>
<form action="" method="post" enctype="multipart/form-data"> {% csrf_token %} <input type="file" name="f1"> <input type="text" name="user"> <input type="submit" value="提交"> </form> </div>
En general, cuando un envío del formulario forma normal, encabezado de la solicitud CONTENT_TYPE: application/x-www-form-urlencoded
, y después los datos se transmiten en forma de pares de valores clave, el servidor desde request.POST
el valor, no hay duda, y CONTENT_TYPE: application/x-www-form-urlencoded
este tipo de codificación para la mayoría de los casos, todo lo muy bueno.
Y decir que el uso de la forma formulario para cargar un archivo, hay que decir unas palabras hacia arriba.
En un primer momento, el protocolo HTTP no está aspectos funcionales de carga de archivos hasta RFC1867 añadir esta funcionalidad al protocolo http. RFC1867 define en el curso de form
la etiqueta method
debe ser POST
, enctype = "multipart/form-data"
así <input type = "file">
.
Por lo tanto, cuando se utiliza el formulario de formulario para subir documentos, solicitud de cabecera content_type
es multipart/form-data
esta forma, por lo que tenemos que añadir una forma de etiqueta enctype="multipart/form-data
atributos para su identificación.
Si puede imprimir encabezado de solicitud para subir archivos, encontrará CONTENT_TYPE
es esto content_type:multipart/form-data; boundary=----WebKitFormBoundarylZZyJUkrgm6h34DU
, que boundary=----WebKitFormBoundarylZZyJUkrgm6h34DU
lo es?
En multipart/form-data
detrás boundary
y una cadena de caracteres, esto es el delimitador, una pila detrás de la cadena generada al azar, con el fin de prevenir la ocurrencia delimitador servidor de archivo de carga no puede identificar correctamente el principio del archivo. Eso delimitador y atenuarla?
Para la solicitud del poste cargue un archivo, no usamos el protocolo http original, por lo multipart / petición form-data se basa en la petición http post original método viene, entonces se dice que la diferencia entre esta nueva manera de enviar la solicitud:
- Solicitar una cabeza diferente, una solicitud de carga de archivos
contentType = multipart/form-data
es necesario, pero después no es, después de todo, no sólo se carguen archivos publican ~. - cuerpo de la solicitud diferente, es diferente se refiere aquí a la antigua (solicitud de carga) se debe utilizar entre cada delimitador de campo para separar la transmisión de contenido, como el contenido y archivos de texto necesitan separadas, de lo contrario el servidor no hay manera de la resolución de archivo normal, que por supuesto hay ningún delimitador posterior directamente
key:value
transmitida en forma ella.
Por supuesto, el curvado alrededor de unas pocas palabras no pueden explicar claramente, sabemos cómo utilizar en la línea.
Look vistas Vista de un proceso:
from django.shortcuts import render, redirect, HttpResponse
from django.db import transaction
def import_case(request, pk): """ 导入Excel数据,pk是所属项目的pk """ if request.method == 'POST': try: with transaction.atomic(): # 事物 # project_pk = request.POST.get("project_pk") # 数据库使用字段 excel = request.FILES.get('file_obj') book = xlrd.open_workbook(filename=None, file_contents=excel.read()) sheet = book.sheet_by_index(0) title = sheet.row_values(0) for row in range(1, sheet.nrows): print(sheet.row_values(row)) # 这里取出来每行的数据,就可以写入到数据库了 return HttpResponse('OK') except Exception as e: print(e) return render(request, 'import_case.html', {"project_pk": pk, "error": "上传文件类型有误,只支持 xls 和 xlsx 格式的 Excel文档"}) return render(request, 'import_case.html', {"project_pk": pk, "error": ""})
subir archivos ajax
La parte delantera del archivo:
<!DOCTYPE html>
<html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <!-- ajax上传文件开始 --> <div> {% csrf_token %} <input type="file" id="ajaxFile"> <button id="ajaxBtn">上传</button> </div> <!-- ajax上传文件结束 --> </body> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> <script> console.log($("[name='csrfmiddlewaretoken']").val()); $("#ajaxBtn").click(function () { // 首先,实例化一个formdata对象 var formData = new FormData(); // 然后使用formdata的append来添加数据,即获取文件对象 // var file_obj = $("#ajaxFile")[0].files[0]; // 使用jQuery获取文件对象 var file_obj = document.getElementById('ajaxFile').files[0]; // 使用dom也行 formData.append('f1', file_obj ); // 处理csrftoken formData.append("csrfmiddlewaretoken", $("[name='csrfmiddlewaretoken']").val()); // 也可以将其他的数据,以键值对的形式,添加到formData中 formData.append('user','张开'); $.ajax({ url: "/upload/", type: "POST", data: formData, processData:false, // contentType:false, success:function (dataMsg) { console.log(dataMsg); } }) }) </script> </html>
Ajax conjunto con el fin de evitar la falsa solicitud contentType jQuery cabeza content_type
opera, perdiendo así delimitador, el servidor de archivos no puede resolver correctamente.
En el uso de método jQuery $ .ajax () cuando el parámetro predeterminado processData a verdadero (que es un jQuery única), el valor predeterminado será el caso de la secuencia de datos transmitida a adaptarse aplicación tipo de contenido predeterminado / x-www-form -urlencoded
tiempo si desea no quieren enviar información a la necesidad de ajustar manualmente a false.
Echemos un vistazo en el back-end de views.py
cómo hacer frente a:
import xlrd
from django.shortcuts import render
from django.http import JsonResponse def upload(request): if request.is_ajax(): # print(request.META['CONTENT_TYPE']) # multipart/form-data; boundary=----WebKitFormBoundaryuXDgAwSKKIGnITam # print(request.POST) # <QueryDict: {'csrfmiddlewaretoken': ['mx1EBTtsOb0k96TUUW8XKbCGvK0Co3S6ZMlLvOuZOKAlO9nfhf6zol0V8KxRxbwT'], 'user': ['张开']}> # print(request.FILES) # <MultiValueDict: {'f1': [<InMemoryUploadedFile: 接口测试示例.xlsx (application/vnd.openxmlformats-officedocument.spreadsheetml.sheet)>]}> f1 = request.FILES.get('f1') print(f1) # 接口测试示例.xlsx book = xlrd.open_workbook(filename=None, file_contents=f1.read()) sheet = book.sheet_by_index(0) print(sheet.row_values(1)) # ['cnodejs项目', 'get /topics 主题首页', 'https://cnodejs.org/api/v1/topics', 'get', '', '{"success":true}'] return JsonResponse({"message": "upload successful"}) else: return render(request, 'upload.html')
OK, decir nada bueno, estaría terminado seco.
descargar
uso StreamingHttpResponse
vistas en el código principal:
from django.http import StreamingHttpResponse
def download(request): file=open('crm/models.py','rb') response =StreamingHttpResponse(file) response['Content-Type']='application/octet-stream' response['Content-Disposition']='attachment;filename="models.py"' return response
uso FileResponse
vistas en el código principal:
from django.http import FileResponse
def download(request): file=open('crm/models.py','rb') response =FileResponse(file) response['Content-Type']='application/octet-stream' response['Content-Disposition']='attachment;filename="models.py"' return response
Nombre de archivo no puede resolver los problemas en China
Si usted tiene cuidado de tratar, se encuentran dos formas de descargar lo anterior filename
no puede contener chino, entonces, ¿cómo se puede solucionar? Mirar hacia abajo!
from django.http import FileResponse
from django.utils.encoding import escape_uri_path # 导入这个家伙 def download(request): file=open('crm/models.py','rb') response =FileResponse(file) response['Content-Type']='application/octet-stream' response['Content-Disposition']='attachment;filename="{}.py"'.format(escape_uri_path("我是中文啦")) return response
No está resuelto! Perfecto! !