Django 文件传输

文件传输,服务器上传至浏览器

分为两种, 直接路由到静态文件,可直接获取
使用 FileResponse 封装

  1. 直接路由到静态文件,可直接获取

    1. 在 settings 文件中设置路径
    2. 直接访问http://<server>/static/<filename>
  2. 使用FileResponse

    	def filetransform(request, *args, **kwargs):
    	    #  设置请求头,设置文件名
    	    ff = open("static/3.xlsx", 'rb')
    	    response = FileResponse(ff, as_attachment=True, filename="5.xlsx")
    	    response['content-type'] = 'application/octet-stream'
    	    response['Content-Disposition'] = 'attachment; filename="{}"'.format("4.xlsx")  # 以此文件名为准
    	    return response
    	
    	def markdown_file(request, *args, **kwargs):
    	    filename = "英语.xmind"
    	    ff = open("static/{}".format(filename), "rb")
    	    # 使用此方法能够避免不同文件造成文件名不可显示
    	    response = FileResponse(ff, as_attachment=True, filename=filename)
    	    return response
    
### Django 中通过 WebSocket 实现文件传输Django实现 WebSocket 文件传输可以通过多种方式完成,其中最常见的是使用 **Django Channels** 或其他轻量级库(如 dwebsocket)。以下是基于这两种方案的具体实现思路。 #### 使用 Django Channels 实现文件传输 Django Channels 提供了一种强大的机制来处理 WebSocket 请求。为了实现文件传输,可以按照以下逻辑设计: 1. 创建一个 WebSocket 消费者类用于接收客户端上传的文件数据并保存到服务器上。 2. 将接收到的数据分片存储,并最终组合成完整的文件。 ##### 步骤说明 - 配置 `asgi.py` 和安装必要的依赖项[^4]。 - 编写自定义消费者类以处理文件流。 ```python import os from channels.generic.websocket import WebsocketConsumer import base64 class FileUploadConsumer(WebsocketConsumer): def connect(self): self.accept() def disconnect(self, close_code): pass def receive(self, text_data=None, bytes_data=None): try: data = eval(text_data) file_name = data.get('file_name') chunk = data.get('chunk') # 解码 Base64 数据 decoded_chunk = base64.b64decode(chunk) # 存储临时文件片段 with open(f'temp_{file_name}', 'ab') as f: f.write(decoded_chunk) # 如果这是最后一部分,则重命名文件 if not chunk.endswith(b'=='): os.rename(f'temp_{file_name}', file_name) self.send(text_data='File upload complete.') except Exception as e: self.send(text_data=f'Error: {str(e)}') ``` 上述代码中,前端需要将文件切分为多个小块并通过 WebSocket 发送至服务端[^5]。 ##### 前端 JavaScript 示例 ```javascript const socket = new WebSocket(`ws://${window.location.host}/ws/file-upload/`); function sendFile(file) { const reader = new FileReader(); let chunksSent = 0; reader.onloadend = () => { const arrayBuffer = reader.result; const byteChunks = []; // 切割文件为固定大小的小块 for (let i = 0; i < arrayBuffer.byteLength; i += CHUNK_SIZE) { byteChunks.push(arrayBuffer.slice(i, i + CHUNK_SIZE)); } function sendNextChunk() { if (chunksSent >= byteChunks.length) return; const chunkData = byteChunks[chunksSent]; const base64String = btoa(String.fromCharCode.apply(null, new Uint8Array(chunkData))); socket.send(JSON.stringify({ file_name: file.name, chunk: base64String })); chunksSent++; setTimeout(sendNextChunk, 10); // 控制发送速率 } sendNextChunk(); }; reader.readAsArrayBuffer(file); } ``` 此脚本会读取本地文件并将它们分割为较小的部分逐一发送给服务器[^2]。 --- #### 使用 DWebSocket 实现文件传输 如果希望简化开发流程,可以选择更便捷的方式——利用 dwebsocket 库。尽管其功能相对有限,但对于简单的应用场景仍然适用。 ##### 后端 Python 示例 ```python from django.http import HttpResponse from dwebsocket.decorators import accept_websocket @accept_websocket def ws_file_upload(request): if request.is_websocket(): message_list = [] temp_filename = None while True: try: msg = request.websocket.wait() if msg is None: break # 处理每一条消息作为文件的一部分 if isinstance(msg, str): # JSON 格式的首包可能包含元信息 meta_info = eval(msg) temp_filename = meta_info['filename'] elif isinstance(msg, bytes): with open(temp_filename, 'ab+') as f: f.write(msg) except Exception as ex: print(ex) continue return HttpResponse("File uploaded successfully.") ``` 该函数会在每次接收到新数据时追加到指定的目标路径下[^1]。 ##### 对应的 HTML 页面 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>WebSocket Upload</title> </head> <body> <input type="file" id="uploadInput"/> <script> document.getElementById('uploadInput').addEventListener('change', async event => { const files = Array.from(event.target.files); await Promise.all(files.map(async file => { const socket = new WebSocket('ws://localhost:8000/ws/upload/'); const reader = new FileReader(); reader.onloadend = () => { const content = reader.result.split('').map(charCode => String.fromCharCode(charCode)).join(''); // Send metadata first socket.send(JSON.stringify({ filename: file.name })); socket.send(content); }; reader.readAsBinaryString(file); })); }); </script> </body> </html> ``` 以上示例展示了如何借助标准浏览器 API 来建立连接并向后端提交二进制资料[^3]。 --- ### 总结 无论是采用 Django Channels 还是 dwebsocket 方法都可以满足基本需求,但前者更适合复杂场景下的大规模部署;后者则适合快速原型验证阶段的需求。具体选择取决于项目的实际规模和技术栈偏好。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值