Django表单上传vcard实时解析不落地存储报错如何解决?
报错原因分析
- 第一个报错
TypeError: expected str, bytes or os.PathLike object, not InMemoryUploadedFile:open()仅接受本地文件路径、字节或路径类对象作为入参,Django表单上传的文件是InMemoryUploadedFile实例,属于内存/临时文件对象,不是本地路径,无法直接传入open()读取。 - 第二个报错
TypeError: cannot use a string pattern on a bytes-like object:直接传入上传文件对象给vobject.readComponents时,读取到的内容是字节格式,而vobject内部解析依赖字符串正则匹配,类型不匹配导致报错。
解决代码
只需要修改视图部分的代码,将上传的二进制文件流包装为文本流即可适配你原有本地解析的逻辑:
import io import vobject from django.shortcuts import render, reverse from django.http import HttpResponseRedirect def upload_vcard(request): data = {} if request.method == "GET": return render(request, "action/upload_test.html", data) vcard_file = request.FILES["vcard"] # 将二进制流包装为文本流,编码可根据vcard实际编码调整,解码报错可尝试替换为'latin-1' with io.TextIOWrapper(vcard_file, encoding='utf-8') as text_stream: for vcard in vobject.readComponents(text_stream): # 原有解析逻辑完全复用 full_name = vcard.contents['fn'][0].value # 其他字段提取逻辑写在这里,提取结果可存入data传给前端渲染 # 如需返回解析结果到前端,替换重定向为render即可 # return render(request, "action/upload_test.html", {"full_name": full_name}) return HttpResponseRedirect(reverse("action:upload_vcard"))
额外说明
- 不需要把vcard存到服务器本地,全程在内存中处理即可满足需求
- 提取字段时注意
vcard.contents['fn']返回的是列表,需要取第一个元素的value属性才能拿到实际的姓名字符串
内容的提问来源于stack exchange,提问作者giaggi
相关产品推荐
相关产品推荐

