IOS 中的服务器返回数据(null)和 <null>的处理方法

本文介绍了当程序遇到&lt;null&gt;时导致崩溃的问题及两种解决方案。第一种方法是使用if语句判断是否等于NSNull,第二种方法是判断对象类型是否为NSNull。文章强调了基础技术的重要性。

这样的“<null>”直接导致程序崩溃了,但是也是一脸懵逼。

然后自己找原因。

这种“<null>”的解决方法有两种

第一种方法是

通过

if([m isEqual:[NSNUll null]])

    NSLog(@"<null>");

}

第二种方法

[m isKindOfClass:[NSNull class]]

基础还是很重要的啊。看似难世纪简单。

<template> <view class="" style="background: #F3F6FA;height: 100vh;overflow: auto;"> <view class="box"> <view class="boxxiao"> <view class=""> <view class="name"> 商品名称 </view> <input v-model="name" class="input" type="text" placeholder="请输入商品名称" /> </view> <view class=""> <view class="name"> 商品编码 </view> <input v-model="productNo" class="input" type="text" placeholder="请输入商品编码" /> </view> <view class=""> <view class="name"> 商品分类 </view> <input v-model="categoryName" @click="openPicker(1)" class="input" type="text" placeholder="请输入商品分类" /> </view> <view class=""> <view class="name"> 品牌 </view> <input v-model="brandName" @click="openPicker(2)" class="input" type="text" placeholder="请输入商品分类" /> </view> <view class=""> <view class="name"> 排序 </view> <input v-model="sort" class="input" type="text" placeholder="请输入排序" /> </view> <view class=""> <view class="name"> 单价 </view> <input class="input" type="text" placeholder="请输入单价" /> </view> <view class=""> <view class="name"> 单位 </view> <input v-model="price" class="input" type="text" placeholder="请输入单位" /> </view> <view class=""> <view class="name"> 重量 </view> <input v-model="weight" class="input" type="text" placeholder="请输入重量" /> </view> <view class=""> <view class="name"> 单位 </view> <input v-model="unit" class="input" type="text" placeholder="请输入单位" /> </view> </view> <view class="boxxiao1"> <view class="statc"> <view class=""> 状态 </view> <view class="statcright"> <view class="xiaj shang"> 上架 </view> <view class="xiaj "> 下架 </view> </view> </view> </view> <view class=""> <view class="updtitle"> 产品图片 </view> <view class="updoimg"> <view class="upindex"> <view class="unindexleft"> 主图 </view> <view class=""> <view class=""> <view class="uplbt"> <view class="imgbox" v-for="(item, index) in fileList" :key="index"> <image class="imgs" :src="item"></image> </view> <image @click="chooseImage" v-if="fileList.length<1" style="width: 156rpx;height: 156rpx;padding: 0 10rpx 10rpx 10rpx;" src="/static/Merchantindex/Frame_17@2x.png" mode=""></image> </view> </view> </view> <view class="text13"> 请上传 大小不超过 5MB 格式为 pngipgjpeg 的文件 </view> </view> <view class="upindex"> <view class="unindexleft" @click="chooseImage"> 轮播图 </view> <view class=""> <view class="uplbt"> <view class="imgbox" v-for="(item, index) in fileList2" :key="index"> <image class="imgs" :src="item"></image> </view> <image @click="chooseImage2" style="width: 156rpx;height: 156rpx;padding: 0 10rpx 10rpx 10rpx;" src="/static/Merchantindex/Frame_17@2x.png" mode=""></image> </view> <view class="text13"> 请上传 大小不超过 5MB 格式为 pngipgjpeg 的文件 </view> </view> </view> </view> <view class="guige"> <view class=""> 规格类型 </view> <view class=""> 添加 </view> </view> <view class="gglxbxo"> <view class=""> <view class="name"> 材质 </view> <input class="input" type="text" placeholder="请输入材质" /> </view> <view class=""> <view class="name"> 颜色 </view> <input class="input" type="text" placeholder="请输入颜色" /> </view> <view class=""> <view class="name"> 销售价格 </view> <input class="input" type="text" placeholder="请输入销售价格" /> </view> <view class="" style="height: 40rpx;"> </view> <view class="upindex"> <view class="unindexleft" @click="chooseImage"> 展示图片 </view> <view class=""> <view class="uplbt"> <view class="imgbox" v-for="(item, index) in fileList2" :key="index"> <image class="imgs" :src="item"></image> </view> <image @click="chooseImage2" style="width: 156rpx;height: 156rpx;padding: 0 10rpx 10rpx 10rpx;" src="/static/Merchantindex/Frame_17@2x.png" mode=""></image> </view> <view class="text13"> 请上传 大小不超过 5MB 格式为 pngipgjpeg 的文件 </view> </view> </view> </view> <view class="tetx"> 详细描述 </view> <view class="container"> <button @click="insertImage">插入图片</button> <editor id="editor" class="rech" placeholder="请输入内容" @input="onInput" @statusbar="statusbar" @ready="onEditorReady"> </editor> </view> </view> </view> <view class="tail"> <view class="taill"> 上传 </view> </view> </view> <uv-picker ref="picker" :columns="columns" @confirm="confirm"></uv-picker> <uv-picker ref="picker1" :columns="columns1" @confirm="confirm1"></uv-picker> </template> <script> import { request, BASE_URL } from '@/utils/request.js'; export default { data() { return { name: "", productNo: "", sort: "", price: "", weight: "", unit: "", categoryName: "", brandName: "", shopIds: "", pic: "", fileList: [], fileList2: [], placeholder: '请输入内容', editorCtx: null, columns: [ [] ], columns1: [ [] ], } }, mounted() { this.getInfo() this.getcategory() this.getbrand() }, methods: { openPicker(ins) { if (ins == 1) { this.$refs.picker.open(); } if (ins == 2) { this.$refs.picker1.open(); } }, confirm(e) { console.log('confirm', e); this.categoryName = e.value[0] }, confirm1(e) { console.log('confirm', e); this.brandName = e.value[0] }, async getInfo() { const res = await request({ url: 'wechat/getInfo', method: 'get' }); this.shopIds = res.shopIds[0] console.log("个人信息", res.shopIds[0]) }, async getcategory() { console.log(this.shopIds) const res = await request({ url: 'pms/category/page?pageNum=1&pageSize=999999', method: 'get' }); console.log("商品分类", res) for (var i = 0; i < res.rows.length; i++) { this.columns[0].push(res.rows[i].name) } }, async getbrand() { console.log(this.shopIds) const res = await request({ url: 'pms/brand/page?pageNum=1&pageSize=99999', method: 'get' }); console.log("品牌分类", res) for (var i = 0; i < res.rows.length; i++) { this.columns1[0].push(res.rows[i].name) } }, chooseImage() { uni.chooseImage({ count: 1, sizeType: ['original', 'compressed'], sourceType: ['album', 'camera'], success: (res) => { console.log(res) this.fileList.push(res.tempFilePaths[0]) // this.uploadFile(res.tempFilePaths[0]); async this.convertToBinary(res.tempFilePaths[0]).then(binaryData => { console.log('二进制数据:', binaryData); const res = await request({ url: 'ommon/upload', method: 'post', data:{ file:binaryData } }); // 你可以在这里处理二进制数据,例如上传到服务器 }).catch(error => { console.error('转换失败:', error); }); } }); }, convertToBinary(filePath) { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.onload = (e) => { resolve(e.target.result); // 成功时返回二进制数据 }; reader.onerror = (error) => { reject(error); // 失败时抛出错误 }; reader.readAsArrayBuffer(filePath); // 读取文件为二进制数据 }); }, chooseImage2() { uni.chooseImage({ count: 1, sizeType: ['original', 'compressed'], sourceType: ['album', 'camera'], success: (res) => { this.fileList2.push(res.tempFilePaths[0]) // this.uploadFile(res.tempFilePaths[0]); } }); }, onEditorReady() { uni.createSelectorQuery().in(this).select('#editor').context((res) => { if (res) { this.editorCtx = res.context; } }).exec(); }, insertImage() { wx.chooseImage({ count: 1, sizeType: ['original', 'compressed'], sourceType: ['album', 'camera'], success: (res) => { const filePath = res.tempFilePaths[0]; this.editorCtx.insertImage({ src: filePath, alt: '图片', width: '100%', height: 'auto', success: () => { console.log('图片插入成功'); } }); } }); } } } </script> <style> @import url("Uploadproduct.css") </style> chooseImage怎么修改
最新发布
08-09
<think>我们正在使用uni-app框架,需要实现图片选择并转换为二进制数据上传的功能。 步骤: 1. 使用uni.chooseImage选择图片 2. 将选择的图片转换为二进制数据(ArrayBuffer) 3. 通过uni.uploadFile上传二进制数据 注意:uni.uploadFile的API要求上传文件的路径(临时路径),但如果我们已经将图片读取为ArrayBuffer,我们可以使用另一个方法:使用uni.request直接发送二进制数据。但是,uni.uploadFile更适合文件上传,因为它可以处理multipart/form-data格式,并且支持进度监听等。 然而,根据问题描述,用户希望将图片转换为二进制数据然后上传。这里有两种方式: 方式一:使用uni.uploadFile,它内部会处理文件为二进制流,但我们不需要显式转换,只需要提供临时文件路径。 方式二:使用uni.request,并手动将图片文件读取为ArrayBuffer,然后作为请求体发送。 但是,uni.uploadFile的API设计就是为了上传文件,而uni.request则用于发送普通的网络请求。如果我们希望直接发送二进制数据(比如作为整个请求体,而不是表单的一部分),那么可以使用uni.request,并设置请求体为ArrayBuffer。 不过,根据用户提供的代码片段,他们希望发送一个包含字段名为'file'的二进制数据。这通常需要以multipart/form-data格式发送,但也可以直接发送二进制流(此时整个请求体就是文件内容,服务器需要能够解析)。 考虑到通用性,这里提供两种方案: 方案一:使用uni.uploadFile(推荐,因为uni-app对文件上传做了封装,更简单) 方案二:使用uni.request发送ArrayBuffer(需要自己读取文件为ArrayBuffer,并设置请求头) 由于用户明确要求“转换为二进制数据上传”,这里重点说明方案二。 具体步骤: 1. 使用uni.chooseImage选择图片,得到临时文件路径。 2. 使用uni.getFileSystemManager().readFile读取文件为ArrayBuffer。 3. 使用uni.request发送请求,设置data为ArrayBuffer,并设置合适的Content-Type。 但是注意:uni.request的data默认会转换为字符串,如果要发送二进制数据,需要设置data为ArrayBuffer,并且设置header的Content-Type为图片的MIME类型,例如'image/jpeg'。 然而,如果服务器要求的是multipart/form-data格式(即表单上传),则不能直接发送ArrayBuffer,而应该使用FormData。但在小程序中,uni.request不支持FormData对象(仅H5支持)。因此,在小程序端,我们只能使用uni.uploadFile来实现表单文件上传。 考虑到跨平台,uni-app中上传文件的最佳实践是使用uni.uploadFile。 因此,我们分两种情况情况1:只需要发送文件本身(整个请求体就是文件二进制),使用uni.request发送ArrayBuffer。 情况2:需要以表单形式上传(包含字段名),使用uni.uploadFile。 由于用户代码中要求字段名为'file',所以应该是情况2,即表单上传。 所以,我们推荐使用uni.uploadFile,因为它直接支持表单上传,并且会自动将文件内容作为二进制数据的一部分。 但是,用户提供的代码示例是使用一个request函数(可能是封装过的),并且data中有一个file字段。在uni-app中,我们可以使用uni.uploadFile来模拟这个行为。 下面分别给出两种方案的代码: 方案一(推荐):使用uni.uploadFile ```javascript uni.chooseImage({ count: 1, success: (res) => { const tempFilePaths = res.tempFilePaths; uni.uploadFile({ url: 'https://example.com/common/upload', // 替换为你的上传地址 filePath: tempFilePaths[0], name: 'file', // 对应后端接收的字段名 formData: { // 这里可以添加额外的表单数据 }, success: (uploadRes) => { console.log(uploadRes); }, fail: (error) => { console.error('上传失败:', error); } }); } }); ``` 方案二:使用uni.request发送ArrayBuffer(整个请求体为图片二进制,没有字段名,仅适用于服务器直接接受整个文件内容的情况) ```javascript uni.chooseImage({ count: 1, success: async (res) => { const tempFilePaths = res.tempFilePaths; // 读取为ArrayBuffer const arrayBuffer = await new Promise((resolve, reject) => { uni.getFileSystemManager().readFile({ filePath: tempFilePaths[0], encoding: 'binary', // 注意:这里encoding设置为'binary',得到的是ArrayBuffer success: (readRes) => { resolve(readRes.data); }, fail: (readError) => { reject(readError); } }); }); // 发送请求 uni.request({ url: 'https://example.com/common/upload', // 替换为你的上传地址 method: 'POST', header: { 'Content-Type': 'image/jpeg', // 根据实际图片类型设置 // 注意:如果服务器要求multipart/form-data,则不能这样设置,因为整个请求体不是表单格式 }, data: arrayBuffer, success: (requestRes) => { console.log(requestRes); }, fail: (requestError) => { console.error('上传失败:', requestError); } }); } }); ``` 但是方案二不符合用户代码中要求的字段名(file)的格式。因此,如果服务器要求的是表单数据(multipart/form-data),则方案二不适用。 结论:在uni-app中,如果要以表单形式上传文件(即包含字段名),请使用方案一(uni.uploadFile)。如果服务器要求整个请求体就是图片二进制,则使用方案二。 由于用户代码中data是一个对象,其中包含file字段,所以应该是表单上传,因此我们推荐方案一。 另外,如果用户确实需要将图片转换为二进制数据(比如ArrayBuffer)并作为表单的一部分,那么在小程序中无法通过uni.request直接实现,因为uni.request不支持FormData(小程序环境)。此时,只能使用uni.uploadFile,它会自动将文件内容作为表单字段的值。 因此,我们最终选择方案一。 但是,如果用户希望像在浏览器中那样使用FormData同时发送多个字段(包括文本多个文件),在uni-app中也可以使用uni.uploadFile,它提供了一个formData参数用于添加额外的表单数据,但注意:uni.uploadFile一次只能上传一个文件(即filePath指向一个文件)。如果需要上传多个文件,可以多次调用uni.uploadFile,或者使用多个字段名(但需要服务器支持)。 所以,如果用户需要同时上传多个文件,可以这样: ```javascript // 上传多个文件(假设选择多张图片) uni.chooseImage({ count: 9, success: (res) => { const tempFilePaths = res.tempFilePaths; let uploadCount = 0; tempFilePaths.forEach((filePath, index) => { uni.uploadFile({ url: 'https://example.com/common/upload', filePath: filePath, name: 'file[]', // 注意:服务器按数组接收,或者根据服务器要求,比如多个文件用同一个字段名,服务器按数组处理 formData: { // 可以添加额外的参数,比如序号 index: index }, success: (uploadRes) => { console.log(`文件${index}上传成功`, uploadRes); uploadCount++; if (uploadCount === tempFilePaths.length) { console.log('全部上传完成'); } }, fail: (error) => { console.error(`文件${index}上传失败:`, error); } }); }); } }); ``` 注意:服务器需要支持同一个字段名(如'file[]')接收多个文件。 总结:在uni-app中,上传文件(尤其是需要以表单形式上传)时,使用uni.uploadFile是最合适的方式。 因此,针对用户的问题,我们推荐使用uni.uploadFile,而不需要显式将图片转换为二进制数据(ArrayBuffer),因为uni.uploadFile内部会处理。 但是,如果用户坚持要得到二进制数据(ArrayBuffer)并自己处理上传,那么可以使用方案二,但要注意服务器是否能接受整个请求体就是图片二进制数据,且没有字段名。 由于用户原始代码中使用了字段名'file',所以这里我们按照方案一实现。 下面给出完整的示例代码(使用uni.uploadFile):</think>在 uni-app 中实现图片选择并转换为二进制数据上传的完整方案如下,分为三个核心步骤: ### 步骤一:选择图片并获取临时路径 ```javascript uni.chooseImage({ count: 1, // 选择1张图片 sourceType: ['album', 'camera'], // 可从相册或相机选择 success: (res) => { const tempFilePath = res.tempFilePaths[0]; this.convertToBinary(tempFilePath); // 进入转换流程 }, fail: (error) => { console.error('选择图片失败:', error); } }); ``` ### 步骤二:将图片转换为二进制数据 ```javascript methods: { convertToBinary(filePath) { // 小程序端使用文件系统API const fs = uni.getFileSystemManager(); fs.readFile({ filePath, encoding: 'binary', // 关键:指定二进制格式 success: (res) => { const binaryData = res.data; this.uploadImage(binaryData); // 进入上传流程 }, fail: (error) => { console.error('转换二进制失败:', error); } }); } } ``` ### 步骤三:上传二进制数据到服务器 ```javascript methods: { uploadImage(binaryData) { uni.request({ url: 'https://your-api-domain/common/upload', method: 'POST', header: { 'Content-Type': 'application/octet-stream' // 二进制流类型 }, data: binaryData, // 直接传递二进制数据 success: (res) => { console.log('上传成功:', res.data); }, fail: (error) => { console.error('上传失败:', error); } }); } } ``` ### 关键注意事项: 1. **跨平台兼容性**: - 小程序端:使用 `uni.getFileSystemManager().readFile` 读取文件 - H5端:可直接使用 `FileReader API` 读取文件 - App端:与小程序实现方式相同 2. **二进制格式指定**: ```javascript // 正确设置编码类型 encoding: 'binary' // 小程序/App // 或 responseType: 'arraybuffer' // H5 ``` 3. **服务器端处理**(Node.js示例): ```javascript app.post('/common/upload', (req, res) => { const binaryData = req.body; // 获取二进制数据 fs.writeFile('upload.jpg', binaryData, (err) => { if (err) return res.status(500).send('保存失败'); res.send('上传成功'); }); }); ``` 4. **大文件优化**: ```javascript // 分片上传示例 const CHUNK_SIZE = 1024 * 1024; // 1MB for (let i = 0; i < binaryData.byteLength; i += CHUNK_SIZE) { const chunk = binaryData.slice(i, i + CHUNK_SIZE); // 上传每个分片... } ``` ### 完整流程图: ```mermaid graph TD A[用户选择图片] --> B[获取临时文件路径] B --> C[读取为二进制数据] C --> D[设置Content-Type头] D --> E[POST发送二进制数据] E --> F[服务器保存文件] ``` ### 常见问题解决: 1. **安卓兼容性问题**:添加 `header: { 'Content-Type': 'application/octet-stream' }` 2. **iOS格式限制**:确保图片格式为常见类型(jpg/png) 3. **H5特殊处理**: ```javascript // H5使用FileReader const reader = new FileReader(); reader.readAsArrayBuffer(file); reader.onload = (e) => { const binaryData = e.target.result; } ``` > 提示:实际开发中建议使用 `uni.uploadFile` API 替代直接发送二进制数据,可自动处理多平台差异[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值