2016-08-29 1 views
4

인증 후/권한이 FileField에 저장된 파일을 제공한다는보기가 있습니다.브라우저에서 django 이진 파일 다운로드가 손상되었습니다.

from django.http import StreamingHttpResponse 
from rest_framework import viewsets 
from rest_framework.decorators import detail_route 
from wsgiref.util import FileWrapper 
import mimetypes 
from myapp.models import MyModel 

class ExampleViewSet(viewsets.ViewSet): 
    # Normal crud (retrive, list, etc.) 
    @detail_route(methods=['GET']) 
    def download(self, *args, **kwargs): 
     pk = self.request.parser_context['kwargs'].get('pk', None) 
     if pk is None: 
      raise exceptions.ParseError('no pk') 
     instance = MyModel.objects.get(pk=pk) 
     filename = instance.file_field.name.split('/')[-1] 
     mime = mimetypes.guess_type(filename)[0] 
     file = instance.file_field.file 
     response = StreamingHttpResponse(
      FileWrapper(open(file, 'rb'), 10240)) 
     response['Content-Type'] = "{0}; charset=utf-8".format(mime) 
     response['Content-Length'] = file.size 
     response[ 
      'Content-Disposition'] = 'attachment; filename={0}'.format(filename) 
     return response 

파일 자체는 이전에 사용자가 업로드 한 3.7MB 파일 jpeg입니다. 업로드 디렉토리에서 파일은 3.7MB이고 올바르게 열립니다. 브라우저 (Firefox 또는 Chrome)를 통해 파일을 다운로드 할 때 파일이 7.0MB이고 손상된 파일 (두 개의 특정 바이트로 시작해야하는 jpeg의 헤더가 올바르지 않음)이 curl 또는 wget에서 다운로드되면 파일이 3.7MB이고 올바르게 열립니다.

다음 는 컬 -v를 사용하여 응답 필드의 컬의 출력

curl -v http://localhost:3000/api/school_admin/posters/7/download?token=ZXlKaGJHY2lPaUpJVXpVeE1pSXNJblI1Y0NJNklrcFhWQ0o5LmV5SndhR0Z6YUNJNkltSmpjbmx3ZEY5emFHRXlOVFlrSkRKaUpERXlKR2hzVlUxd2QyOWpTM1pMTnk1VlRuSXZPR1ZNVWs5aFJEVjBVbmR2V21FeVVGVlZiWGhxTTJWb1UzZFhla1JNU3k5RmFqZFRJaXdpY0hKdlptbHNaVjl3YXlJNk15d2laWGh3SWpveE5EY3lOalUyTWpFMGZRLmV6OGg5SWVwLUozYjdQcHJLVGJCZWlSSjJPN1JRdnItaFVuLVg0dmdLZGdtRGdQV0s2ZzkzdktialN2Uy1EVTVkM1hRc2hRZ3YxeVZmQlJhUDBBVlhB -o test.jpeg 
    % Total % Received % Xferd Average Speed Time Time  Time Current 
           Dload Upload Total Spent Left Speed 
    0  0 0  0 0  0  0  0 --:--:-- --:--:-- --:--:--  0* Trying 127.0.0.1... 
* Connected to localhost (127.0.0.1) port 3000 (#0) 
> GET /api/school_admin/posters/7/download?token=ZXlKaGJHY2lPaUpJVXpVeE1pSXNJblI1Y0NJNklrcFhWQ0o5LmV5SndhR0Z6YUNJNkltSmpjbmx3ZEY5emFHRXlOVFlrSkRKaUpERXlKR2hzVlUxd2QyOWpTM1pMTnk1VlRuSXZPR1ZNVWs5aFJEVjBVbmR2V21FeVVGVlZiWGhxTTJWb1UzZFhla1JNU3k5RmFqZFRJaXdpY0hKdlptbHNaVjl3YXlJNk15d2laWGh3SWpveE5EY3lOalUyTWpFMGZRLmV6OGg5SWVwLUozYjdQcHJLVGJCZWlSSjJPN1JRdnItaFVuLVg0dmdLZGdtRGdQV0s2ZzkzdktialN2Uy1EVTVkM1hRc2hRZ3YxeVZmQlJhUDBBVlhB HTTP/1.1 
> Host: localhost:3000 
> User-Agent: curl/7.43.0 
> Accept: */* 
> 
< HTTP/1.1 200 OK 
< date: Mon, 29 Aug 2016 18:31:30 GMT 
< server: WSGIServer/0.2 CPython/3.4.3 
< allow: GET, DELETE, HEAD, OPTIONS 
< content-type: image/jpeg; charset=utf-8 
< vary: Accept 
< content-length: 3947925 
< content-disposition: attachment; filename=poster_28F7bdD4caAbCc583831c9E7C9baDaEC88Ecbde6FBAA6aE71cAdC09fd8EFCF7BD515155bec1C3FC6f01c6FEf5Ba76e41952E_Colosseum_in_Rome_Italy_-_April_2007.jpg 
< x-frame-options: SAMEORIGIN 
< via: 1.1 fedora 
< Connection: keep-alive 
< 
{ [15913 bytes data] 
100 3855k 100 3855k 0  0 141M  0 --:--:-- --:--:-- --:--:-- 144M 
* Connection #0 to host localhost left intact 

답변

2

nginx + uwsgi를 사용할 때 문제가 해결되었습니다. 나는 Django의 runserver가 수동으로 추가 할 경우 추가 및 오류를 거부하는 'Hop-by-Hop'헤더 중 일부와 관련이 있다고 생각합니다. 일반적으로 역방향 프록시와 관련이 있습니다.

0

ASCII 파일 전송 유형으로 FTP를 통해 파일/데이터를 업로드하면서 일반적으로 발생합니다. "ASCII 전송 유형"은 파일을 일반 텍스트 파일로 전송하므로 아무런 문제가 없습니다. 이지만 "이진 전송 유형"은 텍스트 데이터 대신 이진 데이터로 파일을 처리하는 바이너리 모드로 데이터를 전송합니다. FTP 클라이언트를 바이너리로 설정하면 ftp 전송을 통해 파일이 손상되지 않습니다. FTP 프로그램을 바이너리로 전환하는 방법은 다음을 참조하십시오.

여기서 ASCII의 관점에서 이진 데이터를 시도해야합니다.

+0

파일은 ftp가 아닌 http를 통해 업로드되지만, 그럴 경우에도 브라우저와 동일한 문제에 직면하지 않을 수도 있습니다. 뿐만 아니라 업로드 폴더의 파일도 손상 되었습니까? –

관련 문제