从输入表单获取 Base64 编码文件数据

IT技术 javascript html file-upload base64
2021-01-29 12:31:25

我有一个基本的 HTML 表单,我可以从中获取一些我正在 Firebug 中检查的信息。

我唯一的问题是我试图在将文件数据发送到服务器之前对其进行base64编码,服务器需要以该形式保存到数据库中。

<input type="file" id="fileupload" />

在 Javascript+jQuery 中:

var file = $('#fileupload').attr("files")[0];

我有一些基于可用 javascript 的操作:.getAsBinary(), .getAsText(), .getAsTextURL

然而,这些都没有返回可以插入的可用文本,因为它们包含不可用的“字符” ——我不希望在我上传的文件中出现“回发”,我需要有多个针对特定对象的表单,所以我很重要获取文件并以这种方式使用Javascript。

我应该如何以可以使用广泛可用的 Javascript base64 编码器之一的方式获取文件!?

谢谢

更新 - 从这里开始赏金,需要跨浏览器支持!!!

这是我所在的位置:

<input type="file" id="fileuploadform" />

<script type="text/javascript">
var uploadformid = 'fileuploadform';
var uploadform = document.getElementById(uploadformid);


/* method to fetch and encode specific file here based on different browsers */

</script>

跨浏览器支持的几个问题:

var file = $j(fileUpload.toString()).attr('files')[0];
fileBody = file.getAsDataURL(); // only would works in Firefox

此外,IE 不支持:

var file = $j(fileUpload.toString()).attr('files')[0];

所以我必须替换为:

var element = 'id';
var element = document.getElementById(id);

对于 IE 支持。

这适用于 Firefox、Chrome 和 Safari(但没有正确编码文件,或者至少在发布后文件没有正确显示)

var file = $j(fileUpload.toString()).attr('files')[0];
var encoded = Btoa(file);

还,

file.readAsArrayBuffer() 

好像只支持 HTML5?

很多人建议: http : //www.webtoolkit.info/javascript-base64.html

但这只会在 base64 编码之前在 UTF_8 方法上返回错误?(或空字符串)

var encoded = Base64.encode(file); 
6个回答

这在浏览器端 javascript 中是完全可能的。

简单的方法:

readAsDataURL()方法可能已经对其进行编码为base64为您服务。您可能需要删除开头的内容(直到第一个,),但这没什么大不了的。不过,这会带走所有的乐趣。

艰难的方式:

如果您想以艰难的方式尝试(或不起作用),请查看readAsArrayBuffer(). 这将为您提供一个 Uint8Array,您可以使用指定的方法。这可能仅在您想弄乱数据本身时才有用,例如在上传之前处理图像数据或执行其他巫术魔法。

有两种方法:

  • 转换为字符串并使用内置的btoa或类似的
    • 我没有测试过所有情况,但对我有用 - 只需获取字符代码
  • 直接从 Uint8Array 转换为 base64

我最近在浏览器中实现了tar作为该过程的一部分,我制作了自己的直接 Uint8Array->base64 实现。我认为您不需要那个,但如果您想看一看,它就在这里它很整洁。

我现在应该做什么:

从 Uint8Array 转换为字符串的代码非常简单(其中 buf 是 Uint8Array):

function uint8ToString(buf) {
    var i, length, out = '';
    for (i = 0, length = buf.length; i < length; i += 1) {
        out += String.fromCharCode(buf[i]);
    }
    return out;
}

从那里,只需执行以下操作:

var base64 = btoa(uint8ToString(yourUint8Array));

Base64 现在将是一个 base64 编码的字符串,它应该只上传 peachy。如果你想在推送前仔细检查,试试这个:

window.open("data:application/octet-stream;base64," + base64);

这会将其下载为文件。

其他信息:

要将数据作为 Uint8Array 获取,请查看 MDN 文档:

createObjectURL() <-- 这看起来很有希望我会尝试实现它,但我确定 IE 将需要第三轮
2021-03-18 12:31:25
readAsArrayBuffer() 在 Chrome/Safari 中似乎不存在,我假设在其他浏览器中会出现问题~是否有我可以在这些其他浏览器中使用的等效项?
2021-03-28 12:31:25
@Ωmega - 不。所有这些都是下载二进制流。无法(AFAIK)指定文件名。不过,有些浏览器会猜测扩展名。要获取文件名,您必须上传然后再次下载。
2021-03-30 12:31:25
是否可以在执行下载解决方案之前分配文件名?
2021-04-01 12:31:25
太好了——我认为readAsArrayBuffer()输出看起来像正确的base64数据,但由于字符串的乞求部分而无法处理——我现在就试一试!
2021-04-07 12:31:25

我的解决办法是使用readAsBinaryString()btoa()它的结果。

uploadFileToServer(event) {
    var file = event.srcElement.files[0];
    console.log(file);
    var reader = new FileReader();
    reader.readAsBinaryString(file);

    reader.onload = function() {
        console.log(btoa(reader.result));
    };
    reader.onerror = function() {
        console.log('there are some problems');
    };
}
到目前为止最简单的方法,为什么这没有更多的选票?
2021-03-22 12:31:25

我使用 FileReader 在不使用任何 Ajax 请求的情况下单击文件上传按钮来显示图像。以下是代码希望它可以帮助某人。

$(document).ready(function($) {
    $.extend( true, jQuery.fn, {        
        imagePreview: function( options ){          
            var defaults = {};
            if( options ){
                $.extend( true, defaults, options );
            }
            $.each( this, function(){
                var $this = $( this );              
                $this.bind( 'change', function( evt ){

                    var files = evt.target.files; // FileList object
                    // Loop through the FileList and render image files as thumbnails.
                    for (var i = 0, f; f = files[i]; i++) {
                        // Only process image files.
                        if (!f.type.match('image.*')) {
                        continue;
                        }
                        var reader = new FileReader();
                        // Closure to capture the file information.
                        reader.onload = (function(theFile) {
                            return function(e) {
                                // Render thumbnail.
                                    $('#imageURL').attr('src',e.target.result);                         
                            };
                        })(f);
                        // Read in the image file as a data URL.
                        reader.readAsDataURL(f);
                    }

                });
            });
        }   
    });
    $( '#fileinput' ).imagePreview();
});

灵感来自@Josef 的回答:

const fileToBase64 = async (file) =>
  new Promise((resolve, reject) => {
    const reader = new FileReader()
    reader.readAsDataURL(file)
    reader.onload = () => resolve(reader.result)
    reader.onerror = (e) => reject(e)
  })

const file = event.srcElement.files[0];
const imageStr = await fileToBase64(file)

完整示例

html文件输入

<style>
.upload-button {
  background-color: grey;
}

.upload-button input{
  display:none;
}
</style>
<label for="upload-photo" class="upload-button">
    Upload file
    <input
     type="file"
     id="upload-photo"
    </input>
</label>

JS 处理程序

document.getElementById("upload-photo").addEventListener("change", function({target}){
 if (target.files && target.files.length) {
      try {
        const uploadedImageBase64 = await convertFileToBase64(target.files[0]); 
        //do something with above data string 
      } catch() {
        //handle error
      }
    }
})

function convertFileToBase64(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = () => resolve(reader.result as string);
    reader.onerror = reject;
  });
}
这是基于mb21的答案。
2021-03-17 12:31:25