gpt4 book ai didi

android - 发送 Blob 结果为空

转载 作者:行者123 更新时间:2023-12-03 21:38:37 28 4
gpt4 key购买 nike

在我在 Android 4.0 上测试的 Cordova/Phonegap 应用程序中,我需要将文件作为 multipart/form-data 发送到服务器通过ajax。

我在 ArrayBuffer 中有文件内容我把它放在 FormData ,首先创建一个Blob从中。

问题是发送的文件似乎是空的。

这是一个控制台 session (通过 weinre 在 Android 平台上执行),您可以在其中看到:

  • 文件内容已加载到 mybuf
  • 一个 Blobmybuf 创建(并且它的大小不为零)
  • 一个 FormData创建要发送的对象 (fd)

  • (我使用 WebKitBlobBuilder 因为 Blob 构造函数在此平台上引发了 TypeError)
    ❯ mybuf
    ▼ ArrayBuffer
    byteLength: 23673
    ▶ __proto__: ArrayBuffer
    ❯ var bb = new WebKitBlobBuilder()
    undefined
    ❯ bb.append(mybuf)
    undefined
    ❯ myblob = bb.getBlob("image/jpeg")
    ▼ Blob
    size: 23673
    type: "image/jpeg"
    ▶ __proto__: Blob
    ❯ fd = new FormData()
    ▶ FormData
    ❯ fd.append("pics[]", myblob, "1433412118197.jpg")
    undefined

    当我执行通过 fd 的 ajax 请求时对象作为数据,我看到文件实际上是发送的(我在请求中看到 name="pics[]"),但它的内容是空的。

    这是请求的回声:

    POST /test/post/ HTTP/1.1
    Host: 192.168.1.88:50000
    Connection: keep-alive
    Content-Length: 212
    Origin: file://
    Content-Type: multipart/form-data; boundary=----WebKitFormBoundarywFAAx1aqKBZ6uuOf
    Accept: */*
    User-Agent: Mozilla/5.0 (Linux; U; Android 4.0.4; it-it; M-MP706I Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30
    Accept-Encoding: gzip,deflate
    Accept-Language: it-IT, en-US
    Accept-Charset: utf-8, iso-8859-1, utf-16, *;q=0.7

    ------WebKitFormBoundarywFAAx1aqKBZ6uuOf
    Content-Disposition: form-data; name="pics[]"; filename="Blobd380f922a76d4b03908c426487d2fa68"
    Content-Type: image/jpeg


    ------WebKitFormBoundarywFAAx1aqKBZ6uuOf--

    我也尝试过

    我还尝试构建一个 Uint8Array来自 ArrayBuffer并以多种方式用它构建 Blob,但都没有奏效。 Uint8Array似乎没问题:
    ❯ var myu8buf = new Uint8Array(mybuf)
    undefined
    ❯ myu8buf
    ▼ Uint8Array
    0: 255
    1: 216
    2: 255
    3: 225
    4: 1
    5: 20
    6: 69
    7: 120
    ...

    然后,根据我附加到 BlobBuilder 的内容,Blob 大小变化:
  • bb.append([myu8buf]) - Blob 大小:19
  • bb.append(myu8buf) - Blob 大小:19
  • bb.append([myu8buf.buffer]) - Blob 大小:20
  • bb.append(myu8buf.buffer) - Blob 大小:23673

  • 所以最后一个似乎是正确的,但如果发送它,它的行为与原始 ArrayBuffer 完全相同(即发送空文件)。

    文件读取和 Ajax 函数

    这是我用来发送 FormData 的函数(使用 jQuery):
    function sendform(fd) {
    $.ajax({
    url: 'http://192.168.1.88:50000/test/post/',
    data: fd,
    processData: false,
    contentType: false,
    type: 'POST',
    success: function(d){
    console.log("data received:");
    console.log(d);
    },
    error: function(d) {
    console.log("ajax error!");
    }
    });
    }

    这是读取 ArrayBuffer中文件内容的功能:
    function file2buf(filename, callback) {

    window.resolveLocalFileSystemURL(filename, function(fileEntry) {

    return fileEntry.file(function(file) { // success (fileEntry.file)

    var reader = new FileReader();

    reader.onloadend = function(fileReadResult) {

    console.log("file type: "+file.type);
    console.log("file name: "+file.name);

    callback(fileReadResult.target.result);

    };

    return reader.readAsArrayBuffer(file);

    }, function(e) { // fail (fileEntry.file)
    console.log("ERR in fileEntry.file");
    console.log(e);
    });
    }, function(e) { // fail (resolveLocalFileSystemURL)
    console.log("ERR in resolveLocalFileSystemURL");
    console.log(e);
    });

    }

    最佳答案

    让我们从 FileEntry 开始或 Entry (由相机提供)。您必须将该条目转换为 Blob
    这是一种可以为您完成的方法。请注意,这会将对象加载到内存中,我找不到解决方法,因为没有从文件系统流式传输的能力。

      private async fileEntryToBlob(entry: Entry): Promise<Blob> {

    if (!entry.isFile) {
    throw Error(`expected ${entry} to be a file`);
    }
    const fileEntry = (entry as FileEntry);
    return new Promise<Blob>(
    (resolve, reject) => {

    fileEntry.file(
    (file) => {
    const reader = new FileReader();
    reader.onloadend = function (evt) {
    resolve(new Blob([evt.target.result]));
    }
    reader.readAsArrayBuffer(file);
    },
    (err) => { reject(err); },
    );

    });
    }
    该 blob 可以附加到 FormData如此处所示的 promise 。
      /**
    * Uploads an artifact to the backend and returns a promise for
    * the upload result. Progress cannot be tracked with this one.
    *
    * @param fileEntry file entry to upload
    */
    public async uploadFile(fileEntry: Entry): Promise<IUploadResult> {
    const url = ....

    const blob: Blob = await this.fileEntryToBlob(fileEntry);
    const formData = new FormData();
    formData.append("uploadFile", blob, fileEntry.name);
    return this.http
    .post<IUploadResult>(
    url,
    formData
    )
    .toPromise();
    }
    这是另一个作为可观察流的。
     /**
    * Uploads an artifact to the backend and returns an observable of
    * HttpEvents. That way progress can be tracked.
    *
    * @param fileEntry file entry to upload
    */
    public uploadFile$(fileEntry: Entry): Observable<HttpEvent<IUploadResult>> {
    const url = ...

    const formData$ = defer(async () => {
    const blob: Blob = await this.fileEntryToBlob(fileEntry);
    const formData = new FormData();
    formData.append("uploadFile", blob, fileEntry.name);
    return formData;
    });

    return formData$.pipe(
    mergeMap(formData =>
    this.http
    .post<IUploadResult>(
    url,
    formData,
    {
    reportProgress: true,
    observe: "events",
    }
    )
    )
    )
    }

    关于android - 发送 Blob 结果为空,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30646434/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com