【问题标题】:Upload base64 image as a like file input with file name using AJAX使用 AJAX 将 base64 图像上传为带有文件名的类似文件输入
【发布时间】:2021-01-05 08:40:20
【问题描述】:

在服务器端,我有 spring MVC (JAVA) 项目,它接受带有MultipartFile 的多部分/表单数据

@RequestMapping(value = { "/uploadImg/**" }, method = RequestMethod.POST)
public void uploadImg(Model model, HttpServletRequest request,HttpServletResponse response,MultipartFile file ) 
{
     String originalFileName = file.getOriginalFilename();
     //some cases on based on file name and storing the file into the server
}

以前,我使用<fomr><file> 来上传文件。但现在我有一个 base64 格式的图像数据,想使用 AJAX 上传到相同的请求映射。

我遇到了这个Upload base64 image with Ajax 和很多这样的解决方案。但是所有人都只上传文件数据,但在我的情况下,我想上传带有数据和名称的图像,因为在服务器端,一些逻辑是基于文件名编写的。

一个选项可能是,在参数中发送图像数据,在另一个参数中发送文件名,但我无权访问(或者更确切地说,我无法更改)服务器端代码来执行此操作。

那么,如何使用 AJAX 上传 base64 图像数据和文件名?

【问题讨论】:

  • @ahendwh2 不,这无济于事。正如我所说,它将在两个请求参数中发送文件数据和文件名。这将需要更改服务器代码。对吗?
  • 我写评论的时间不多。我已经在下面发布了一个完整的答案

标签: javascript jquery ajax


【解决方案1】:

我使用 PHP 服务器测试了以下代码。我无权访问 Spring MVC 服务器,但两者的 JS 代码应该相同。代码主要基于这篇文章:https://ourcodeworld.com/articles/read/322/how-to-convert-a-base64-image-into-a-image-file-and-upload-it-with-an-asynchronous-form-using-jquery

// I've shortend the base64 data to keep this answer short. See the linked article for the complete data
let ImageURL = "data:image/gif;base64,R0lGODlhPQBEAPeoAJosM....";

let block = ImageURL.split(";");
let contentType = block[0].split(":")[1];// In this case "image/gif"
let realData = block[1].split(",")[1];// In this case "R0lGODlhPQBEAPeoAJosM...."

let blob = b64toBlob(realData, contentType);

let formDataToUpload = new FormData();
formDataToUpload.append("image", blob, 'filename.gif'); // Here you can set the filename

$.ajax({
    url: '/upload.php',
    data: formDataToUpload,
    type: 'POST',
    contentType: false,
    processData: false
});

/**
 * Convert a base64 string in a Blob according to the data and contentType.
 *
 * @param b64Data {String} Pure base64 string without contentType
 * @param contentType {String} the content type of the file i.e (image/jpeg - image/png - text/plain)
 * @param sliceSize {int} SliceSize to process the byteCharacters
 * @see http://stackoverflow.com/questions/16245767/creating-a-blob-from-a-base64-string-in-javascript
 * @return Blob
 */
function b64toBlob(b64Data, contentType, sliceSize) {
    contentType = contentType || '';
    sliceSize = sliceSize || 512;

    let byteCharacters = atob(b64Data);
    let byteArrays = [];

    for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
        let slice = byteCharacters.slice(offset, offset + sliceSize);

        let byteNumbers = new Array(slice.length);

        for (let i = 0; i < slice.length; i++) {
            byteNumbers[i] = slice.charCodeAt(i);
        }

        let byteArray = new Uint8Array(byteNumbers);

        byteArrays.push(byteArray);
    }

    return new Blob(byteArrays, {type: contentType});
}

【讨论】:

    【解决方案2】:

    最好的办法是更改生成此 base64 版本的任何内容,以便它直接返回 Blob。

    如果没有这样的选项,您仍然可以自己将该 base64 字符串转换为 Blob。 获得 Blob 后,您将能够使用 XMLHttpRequestfetch 将其发布到您的服务器,就像 html &lt;form&gt; 一样,感谢 FormData API

    // a 1x1px png image as base64
    const b64 = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWNgYGBgAAAABQABh6FO1AAAAABJRU5ErkJggg==";
    
    // set it to the "name" attribute of your <input type="file">
    const the_name_of_your_previous_file_input = "file";
    // set it to whatever filename you want
    const the_file_name = "pixel.png";
    
    const blob = new Blob([base64ToArrayBuffer(b64)]);
    const form = new FormData();
    form.append(the_name_of_your_previous_file_input, blob, the_file_name);
    
    console.log(...form);
    
    /* Uploads are commented since not working in StackSnippets
    // for modern browsers you can use fetch API
    fetch(YOUR_SERVER_URL, { method: "post", body: form } ); 
    // or for older browsers
    const xhr = new XMLHttpRequest();
    xhr.open("POST", YOUR_SERVER_URL);
    xhr.send(form);
    */
    
    function base64ToArrayBuffer(base64) {
      const binary_str = atob(base64);
      const arr = new Uint8Array(base64.length);
      for(let i=0; i<arr.length; i++) {
        arr[i] = binary_str.charCodeAt(i);
      }
      return arr.buffer;
    }

    【讨论】:

      猜你喜欢
      • 2021-12-30
      • 2022-01-06
      • 2020-04-17
      • 2012-12-19
      • 1970-01-01
      • 2016-11-28
      • 2020-09-05
      • 1970-01-01
      • 2012-04-09
      相关资源
      最近更新 更多