HarmonyOS 鸿蒙Next中media文件下图片上传,后台接收不到

HarmonyOS 鸿蒙Next中media文件下图片上传,后台接收不到 上传图片,有沙箱路径图片,有media 文件夹下文件,沙箱路径文件没有问题,可以上传,传递的都是AarrayBuffer,代码如下

沙箱路径的图片传输方式:

const multiFormData: http.MultiFormData[] = [];
let path: string = image.substring(startIndex);
//本地路径图片
const file = fs.openSync(path, fs.OpenMode.READ_ONLY);

const stat = fs.lstatSync(path);

const buf = new ArrayBuffer(stat.size);

fs.readSync(file.fd, buf);

fs.closeSync(file.fd);

console.log("buf:",JSON.stringify(buf))

multiFormData.push({

  name: 'files', 
  data: buf,

  remoteFileName: `file${i}.png`,

  contentType: 'image/png'

});

media文件夹下的图片传输方法,打印media有数据,后台拿不到,

let context = getContext(this);
try {
  context.resourceManager.getMediaByName(path, (error: BusinessError, value: Uint8Array) => {
    if (error != null) {
      console.error("error is " + error);
    } else {
      let  media = value;
      console.log("this.media:",media)

      multiFormData.push({

        name: 'files', 

        data: media.buffer,

        remoteFileName: `file${i}.png`,

        contentType: 'image/png'

      });

    }
  });
} catch (error) {
  let code = (error as BusinessError).code;
  let message = (error as BusinessError).message;
  console.error(`callback getMediaContent failed, error code: ${code}, message: ${message}.`);
}

cke_12499.png

传输的都是ArrayBuffer,为什么media.buffer,后台(

@RequestPart("files") MultipartFile[] files

)获取不到files?


更多关于HarmonyOS 鸿蒙Next中media文件下图片上传,后台接收不到的实战教程也可以访问 https://www.itying.com/category-93-b0.html

4 回复

根据鸿蒙文档和问题描述,您在上传图片时,从沙箱路径读取的图片可以成功上传,但从media文件夹下使用resourceManager.getMediaByName获取的图片上传时后台接收不到(返回错误"Required request part ‘files’ is not present")。以下是对问题的分析、原因和解决方案:

问题分析

  1. 代码逻辑差异

    • 沙箱路径图片:使用同步方法fs.readSync读取文件内容到ArrayBuffer,并直接添加到multiFormData中。由于是同步操作,上传代码可以在数据准备好后立即执行。
    • media文件夹图片:使用异步方法resourceManager.getMediaByName(回调形式)获取Uint8Array,然后使用其buffer属性作为ArrayBuffer。但您的上传代码可能在没有等待异步回调完成的情况下就执行了,导致multiFormData在回调完成前为空或未包含完整数据。
  2. 后台错误提示:错误"Required request part ‘files’ is not present"表明后台没有收到名为’files’的多部分表单数据部分。这通常是因为上传请求中multiFormData数组为空或未正确填充。

  3. 数据内容验证:从您的日志看,getMediaByName返回的Uint8Array数据是有效的PNG文件(以137,80,78,71开头,即PNG魔法数字),所以数据本身是正确的。问题在于异步时序控制。

原因确定

根本原因是异步操作未完成就执行了上传。对于media文件夹的图片,getMediaByName是异步回调,您的上传代码可能在回调完成前就触发了,导致multiFormData中没有包含预期的数据。

解决方案

为确保所有异步操作完成后再上传,您需要将异步回调转换为Promise形式,并使用Promise.all等待所有文件数据准备好。以下是修改后的代码示例:

import { BusinessError } from '@kit.BasicServicesKit';
import { resourceManager } from '@kit.LocalizationKit';
import { common } from '@kit.AbilityKit';

// 获取context,假设在组件内
let context: common.Context = getContext(this) as common.Context;

// 假设imageNames是media资源名称数组,例如['img01', 'img02']
let imageNames: string[] = ['img01', 'img02']; // 根据实际调整

// 创建一个函数来异步获取media资源的ArrayBuffer
async function getMediaArrayBuffer(imageName: string): Promise<ArrayBuffer> {
  return new Promise<ArrayBuffer>((resolve, reject) => {
    context.resourceManager.getMediaByName(imageName, (error: BusinessError, value: Uint8Array) => {
      if (error) {
        reject(error);
      } else {
        // 确保ArrayBuffer只包含有效数据:创建一个新的ArrayBuffer,复制Uint8Array的数据
        let media = value;
        let newBuffer = new ArrayBuffer(media.length);
        let view = new Uint8Array(newBuffer);
        view.set(media); // 复制数据到新Buffer
        resolve(newBuffer);
      }
    });
  });
}

// 上传函数
async function uploadImages() {
  const multiFormData: http.MultiFormData[] = [];
  
  // 首先处理沙箱路径图片(同步方式,保持不变)
  // ... 您的现有代码 for 沙箱路径 ...
  // 例如:
  // let path: string = ...;
  // const file = fs.openSync(path, fs.OpenMode.READ_ONLY);
  // const stat = fs.lstatSync(path);
  // const buf = new ArrayBuffer(stat.size);
  // fs.readSync(file.fd, buf);
  // fs.closeSync(file.fd);
  // multiFormData.push({ name: 'files', data: buf, remoteFileName: 'file.png', contentType: 'image/png' });

  // 然后处理media文件夹图片:使用Promise.all等待所有异步操作
  try {
    const buffers = await Promise.all(imageNames.map(name => getMediaArrayBuffer(name)));
    buffers.forEach((buffer, index) => {
      multiFormData.push({
        name: 'files',
        data: buffer,
        remoteFileName: `file_media_${index}.png`,
        contentType: 'image/png'
      });
    });
  } catch (error) {
    console.error(`Failed to get media resources: ${error.code}, ${error.message}`);
    return;
  }

  // 现在multiFormData包含所有数据,执行上传
  // 您的上传代码,例如使用http模块发送multiFormData
  // let response = await http.request(..., { data: multiFormData, ... });
  console.log('Uploading with multiFormData:', multiFormData.length);
}

关键点说明

  1. 异步控制:使用Promise.all等待所有getMediaByName回调完成,确保multiFormData填充后再上传。
  2. 数据复制:创建新的ArrayBuffer并复制Uint8Array的数据,避免潜在的原生buffer包含额外数据(虽然通常不是问题,但确保数据精确)。
  3. 错误处理:添加了错误处理,防止单个资源获取失败影响整体。

注意事项

  • 如果您需要混合处理沙箱路径和media文件夹的图片,确保所有操作都完成后再上传。沙箱路径是同步的,所以可以直接放入multiFormData,但media文件夹是异步的,需要等待。
  • 上传代码本身应该在上述异步操作完成后调用,例如在uploadImages函数中执行http请求。

通过以上调整,后台应该能正确接收来自media文件夹的图片数据。如果问题依旧,请检查上传代码中http请求的配置(如URL、方法、头等),确保与沙箱路径上传时一致。

更多关于HarmonyOS 鸿蒙Next中media文件下图片上传,后台接收不到的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


确实是这个原因,后来我断点调试发现了这个问题,我换了一个同步的方法就可以了,你提供的这个方法也可以,谢谢,

在HarmonyOS Next中,图片上传失败可能由多种原因导致。首先检查上传代码是否使用了正确的API接口,确保路径和参数无误。其次,确认网络权限是否开启,并验证服务器端接口是否正常。另外,注意文件格式和大小限制,部分服务器对接收的文件有特定要求。还需排查是否有跨域问题,以及请求头是否正确设置。建议使用抓包工具检查请求是否成功发出及服务器响应内容。

问题可能出在media.buffer的处理方式上。Uint8Array的buffer属性返回的是ArrayBuffer,但需要注意其byteOffset和byteLength。建议在传输前先通过slice()方法确保完整的二进制数据:

const arrayBuffer = media.buffer.slice(media.byteOffset, media.byteOffset + media.byteLength);
multiFormData.push({
  name: 'files',
  data: arrayBuffer,
  remoteFileName: `file${i}.png`,
  contentType: 'image/png'
});

同时检查后台接收代码是否正确处理ArrayBuffer格式的数据。建议在传输前后分别打印ArrayBuffer的byteLength进行对比验证。

回到顶部