【问题标题】:How to append a file to a FormData() from a URL or file on server rather than a file input如何从服务器上的 URL 或文件而不是文件输入将文件附加到 FormData()
【发布时间】:2022-01-21 21:18:20
【问题描述】:

我正在使用 Stripe Connect API 编写一段代码,用户可以通过 jQuery 将 input type="file" 的视觉效果发送到 AJAX 调用,这样:

var form_file = new FormData();
form_file.append('file', document.querySelector('input#file_to_send').files[0]);

当用户提交表单时,我通过 PHP 将视觉对象复制到服务器上的文件夹中,并将其名称保存在会话变量中。 如果表单中的某些内容不正确或缺失,用户将返回同一页面,其中视觉对象显示在 input type="file" 元素下的 img 元素中,因此用户知道他们的视觉对象已被考虑在内。

在那之后,我需要再次在 AJAX 调用中发送文件...除了这一次,不能再从 input type="file" 中选择文件,我唯一可以访问的来源就是取它的名字来自 JavaScript 中的 img 元素。

现在,如果我这样做:

var form_file = new FormData();
form_file.append('file', $('img#visual').attr('src'));

并通过相同的 AJAX 调用发送:

$.ajax({
    url: 'https://uploads.stripe.com/v1/files',
    type: 'POST',
    processData: false,
    contentType: false,
    headers: {'Authorization': 'Bearer xxxxxxxxxxxxxxxxx' },
    data: form_file
}).fail(function(e) {
    console.log('fail: ' + e);
}).done(function(e) {
    console.log('file uploaded: ' + e.id);
});

你猜对了,我的问题是:有没有办法/我应该如何发送文件,而不是从 input 元素作为源发送文件,而是从 img 元素获取定义的路径?

【问题讨论】:

  • 我会用 PHP 来做。您的 formData 发送 URL,然后 PHP 将 URL 与 cURL 请求或 file_get_contents() 一起使用。
  • 不知道该怎么做...请你画一个小草稿好吗? :-)

标签: javascript jquery ajax post form-data


【解决方案1】:

我第二遍看了你的问题。如果我理解正确,您需要向 stripe.com 发送跨域 AJAX 请求,所以您不是在控制服务器端的 PHP 代码,对吧?

简短回答:

最简单的方法是使用 Javascript 而不是 PHP 进行表单检查,因此您无需返回并“丢失”选定的输入文件。


...但是如果您确实需要/想要仅使用其 URL 发送跨域文件

然后您需要将 Data URI 转换为 File,然后附加到 FormData

1/ 获取图片 base64 值

function toDataUrl(url, callback) {
    var xhr = new XMLHttpRequest();
    xhr.onload = function() {
        var reader = new FileReader();
        reader.onloadend = function() {
            callback(reader.result);
        }
        reader.readAsDataURL(xhr.response);
    };
    xhr.open('GET', url);
    xhr.responseType = 'blob';
    xhr.send();
}

2/ 将base64图像转换为Blob:

function DataURIToBlob(dataURI: string) {
    const splitDataURI = dataURI.split(',')
    const byteString = splitDataURI[0].indexOf('base64') >= 0 ? atob(splitDataURI[1]) : decodeURI(splitDataURI[1])
    const mimeString = splitDataURI[0].split(':')[1].split(';')[0]

    const ia = new Uint8Array(byteString.length)
    for (let i = 0; i < byteString.length; i++)
       ia[i] = byteString.charCodeAt(i)

    return new Blob([ia], {
       type: mimeString
    })
 }

3/ 使用 FormData 向您发送 Blob:

const file = DataURIToBlob(imgBase64)
const formData = new FormData();
formData.append('upload', file, 'image.jpg')

来源:


编辑:

您可以使用 Fetch API 直接获取图像 Blob,从而加快阶段 1 和 2。

(警告:与 IE 不兼容)

来源:How to get a File() or Blob() from an URL in javascript?

【讨论】:

    【解决方案2】:

    谢谢@e-telier!将您的代码示例与您建议的链接上的内容相结合后,我能够实现我想要的!这是我最终得到的代码:

    var visual_source = 'upload/file-source.png';
    var visual_ext = visual_source.split('.').pop();
    var visual = await fetch(visual_source);
    console.log(visual);
    var visual_as_blob = await visual.blob();
    console.log(visual_as_blob);
    var visual_as_file = new File([visual_as_blob], 'file-name-renamed.' + visual_ext, { lastModified: new Date().getTime(), type: visual_as_blob.type });
    console.log(visual_as_file);
    form_file.append('file', visual_as_file);
    

    如果有人需要此代码并希望逐步查看正在发生的事情的结果,我会在每个步骤中添加一个 console.log()。步骤是:

    • 我们从给定的 url 获取文件(这里是服务器上“上传”文件夹中的文件)
    • 我们将获取的数据设置为 blob
    • 我们将 blob 转换为文件
    • 然后我们可以将文件 append() 到 FormData() 元素中

    之后,可以通过 ajax 将其发送到 Stripe API。

    再次感谢您的帮助!! :))

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-19
      • 2020-10-19
      • 2017-12-25
      • 2014-03-21
      • 1970-01-01
      相关资源
      最近更新 更多