React Native+DRF项目:图片上传后cv2.imread报文件名转换错误
React Native + DRF 图片上传报错:TypeError: Can't convert object to 'str' for 'filename'
开发React Native前端+Django REST Framework后端应用,前端通过FormData向后端发送图片时触发错误:TypeError: Can't convert object to 'str' for 'filename'。使用本地绝对路径测试接口正常,但处理前端上传的图片时出现该错误。
前端代码
const estPrice = async () => { const formData = new FormData(); console.log(Page1) formData.append("book_page1", { name: "page1.jpg", uri: Page1, type: "image/jpg", }); formData.append("book_page2", { name: "page2.jpg", uri: Page2, type: "image/jpg", }); formData.append("book_page3", { name: "page3.jpg", uri: Page3, type: "image/jpg", }); try { const result = await authAxios.post("/sell/estprice", formData); console.log(result) } catch (error) { console.log(error); } };
后端代码
class BookEstimatedPriceView(GenericAPIView): def post(self, request): data = request.data print(data) img1 = data.get('book_page1', ''); img2 = data.get('book_page2', ''); img3 = data.get('book_page3', ''); print(img1) def rgb_to_hex(rgb_color): hex_color = "#" for i in rgb_color: i = int(i) hex_color += ("{:02x}".format(i)) return hex_color # img1 = 'C:/Users/Aditya Pandit/Desktop/Image/Aditya@123/photo1.jpg' # img2 = 'C:/Users/Aditya Pandit/Desktop/Image/Aditya@123/photo2.jpg' # img3 = 'C:/Users/Aditya Pandit/Desktop/Image/Aditya@123/photo3.jpg' img1 = cv2.imread(img1) img2 = cv2.imread(img2) img3 = cv2.imread(img3) img1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY) img2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY) img3 = cv2.cvtColor(img3, cv2.COLOR_BGR2GRAY) n_clusters = 1 list_hex = [] img_list = [img1, img2, img3] for item in img_list: kmeans = KMeans(n_clusters) kmeans.fit(item) colors = kmeans.cluster_centers_ labels = kmeans.labels_ label_count = [0 for i in range(n_clusters)] for ele in labels: label_count[ele] += 1 index_color = label_count.index(max(label_count)) dict_colour_percen = {} print for index, ele in enumerate(label_count): #print(str(ele)+' labels with pixel value -> '), hex_color = rgb_to_hex(colors[index]) #print(hex_color,) list_hex.append(hex_color) color_percen = float(ele)/len(labels)*100 print('Percentage ->'+str(color_percen)) dict_colour_percen[hex_color] = color_percen print() plt.show() print() list_first_index = [] for items in list_hex: list_first_index.append(items[1:2]) print(list_first_index) price = 200 estimated_price = 0 list_per = [] for items in list_first_index: #for color in list_color_palette: if(items=='0' or items=='1'): list_per.append(20) if(items=='2'): list_per.append(26.3) if(items=='3'): list_per.append(32.6) if(items=='4'): list_per.append(38.9) if(items=='5'): list_per.append(45.2) if(items=='6'): list_per.append(51.5) if(items=='7'): list_per.append(57.8) if(items=='8'): list_per.append(64.1) if(items=='9'): list_per.append(70.4) if(items=='a'): list_per.append(76.7) if(items=='b'): list_per.append(83) if(items=='c'): list_per.append(89.3) if(items=='d'): list_per.append(90) if(items=='e'): list_per.append(90) if(items=='f'): list_per.append(90) print(list_per) sum = 0 for item in list_per: sum+=item avg_per=sum/len(list_per) print(avg_per) estimated_price = price*(avg_per/100) print(estimated_price) data = { 'est_price': estimated_price } return Response(data, status=status.HTTP_200_OK);
报错信息
Internal Server Error: /api/sell/estprice Traceback (most recent call last): File "C:\Users\Aditya Pandit\.virtualenvs\bookmart-ySyK5Yky\Lib\site-packages\django\core\handlers\exception.py", line 55, in inner response = get_response(request) ^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\Aditya Pandit\.virtualenvs\bookmart-ySyK5Yky\Lib\site-packages\django\core\handlers\base.py", line 197, in _get_response response = wrapped_callback(request, *callback_args, **callback_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\Aditya Pandit\.virtualenvs\bookmart-ySyK5Yky\Lib\site-packages\django\views\decorators\csrf.py", line 56, in wrapper_view return view_func(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\Aditya Pandit\.virtualenvs\bookmart-ySyK5Yky\Lib\site-packages\django\views\generic\base.py", line 104, in view return self.dispatch(request, *args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\Aditya Pandit\.virtualenvs\bookmart-ySyK5Yky\Lib\site-packages\rest_framework\views.py", line 509, in dispatch response = self.handle_exception(exc) ^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\Aditya Pandit\.virtualenvs\bookmart-ySyK5Yky\Lib\site-packages\rest_framework\views.py", line 469, in handle_exception self.raise_uncaught_exception(exc) File "C:\Users\Aditya Pandit\.virtualenvs\bookmart-ySyK5Yky\Lib\site-packages\rest_framework\views.py", line 480, in raise_uncaught_exception raise exc File "C:\Users\Aditya Pandit\.virtualenvs\bookmart-ySyK5Yky\Lib\site-packages\rest_framework\views.py", line 506, in dispatch response = handler(request, *args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\Aditya Pandit\Desktop\bookmart\bookmart\sell\views.py", line 70, in post img1 = cv2.imread(img1) ^^^^^^^^^^^^^^^^ TypeError: Can't convert object to 'str' for 'filename'
解决方案
问题本质
DRF接收FormData上传的图片时,request.data.get('book_page1')返回的是InMemoryUploadedFile对象,而非本地文件路径字符串。cv2.imread()仅接受字符串路径或特定格式的文件流,直接传入对象会触发类型错误。
方法一:直接读取文件字节流转换为OpenCV格式
修改后端中读取图片的逻辑,无需保存文件到本地:
import cv2 import numpy as np # 新增工具函数 def read_uploaded_image(uploaded_file): if not uploaded_file: return None # 读取文件字节并转换为numpy数组 file_bytes = np.frombuffer(uploaded_file.read(), np.uint8) # 解码为OpenCV可处理的图片格式 return cv2.imdecode(file_bytes, cv2.IMREAD_COLOR) # 替换原有的图片读取代码 img1 = read_uploaded_image(data.get('book_page1')) img2 = read_uploaded_image(data.get('book_page2')) img3 = read_uploaded_image(data.get('book_page3')) # 后续灰度转换前先判断图片是否有效 if img1 is not None: img1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY) if img2 is not None: img2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY) if img3 is not None: img3 = cv2.cvtColor(img3, cv2.COLOR_BGR2GRAY)
方法二:临时保存文件后读取路径(可选)
如果需要保留cv2.imread()的调用方式,可以先将上传文件保存到临时目录:
from django.core.files.storage import default_storage from django.core.files.base import ContentFile # 保存文件到临时路径 if data.get('book_page1'): temp_file1 = default_storage.save('temp/page1.jpg', ContentFile(data.get('book_page1').read())) img1 = cv2.imread(default_storage.path(temp_file1)) # img2、img3同理 # 注意:需定期清理temp目录下的临时文件,避免存储空间占用
前端额外检查
React Native中上传图片时,Android与iOS的uri格式存在差异:
- Android uri通常为
content://开头,axios会自动处理FormData的Content-Type,无需手动设置。 - iOS uri需确保为
file://前缀,确认Page1/Page2/Page3变量的格式正确。
内容的提问来源于stack exchange,提问作者Kratos
相关产品推荐
相关产品推荐

