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

Posted

技术标签:

【中文标题】从输入表单中获取 Base64 编码文件数据【英文标题】:Get Base64 encode file-data from Input Form 【发布时间】:2011-10-22 03:10:03 【问题描述】:

我有一个基本的 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

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

var encoded = Base64.encode(file); 

【问题讨论】:

你在上传什么?文本数据还是二进制数据? @tjamenson 二进制数据——任何真正的 'word 文档' 'pdf' 'image' 等等。我打算在另一个变量中分配文件名,但我开始怀疑我是否有一些致命的缺陷据我了解上传表单和 html 的可能性 - 这种方法是否完全不可行,并且无法通过将文件数据作为字符串发布来传输文件数据?也没有我正在阅读的 HTML5 有一些解决方案 - 有趣。为什么您在浏览器和服务器之间使用 base-64 编码,并试图在浏览器中完成此操作?似乎如果您尝试保护数据,SSL 会更容易,因为它会通过网络加密所有 HTTP 数据(包括文件)。如果您的数据库需要,您可以使用 base-64 服务器端。 @William 我不是要保护数据,只是将其转换为正确的格式。 Salesforce.com(Apex 平台)要求在数据库中创建记录之前对数据库进行 base64 编码,它们通过表单对文件数据进行 base64 编码的功能记录很差(我想出了如何去做这在问了这个问题之后)。无论如何,看起来 base64 编码二进制文件数据仅在 HTML5Mozilla File API 中受本地支持 好的,现在我明白你为什么需要这个了。没有中间服务器 + 疯狂的云需求 + 没有跨浏览器解决方案 = 1 乱七八糟。对不起。 【参考方案1】:

在浏览器端的javascript中完全可以。

简单的方法:

readAsDataURL() 方法可能已经为您将其编码为 base64。你可能需要去掉开头的东西(直到第一个,),但这没什么大不了的。不过,这会带走所有的乐趣。

艰难的道路:

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

有两种方法:

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

我最近实现了tar in the browser。作为该过程的一部分,我制作了自己的直接 Uint8Array->base64 实现。我不认为你会需要那个,但如果你想看看,那就是here;挺好看的。

我现在做什么:

从 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 编码的字符串,它应该只上传桃色。如果你想在推送前仔细检查,试试这个:

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

这会将其下载为文件。

其他信息:

要以 Uint8Array 形式获取数据,请查看 MDN 文档:

https://developer.mozilla.org/en/DOM/FileReader

【讨论】:

太棒了——我认为readAsArrayBuffer() 输出看起来像正确的 base64 数据,但由于字符串的乞求部分,它不会处理——我会现在试一试! readAsArrayBuffer() 在 Chrome/Safari 中似乎不存在,我假设在其他浏览器中会出现问题 ~ 有没有可以在这些其他浏览器中使用的等效项? createObjectURL() 是否可以在执行下载解决方案之前指定文件名? @Ωmega - 不。所有这些都是下载二进制流。无法(AFAIK)指定文件名。不过,有些浏览器会猜测扩展名。要获取文件名,您必须先上传然后再下载。【参考方案2】:

我开始认为使用“iframe”进行 Ajax 样式上传对于我的情况来说可能是一个更好的选择,直到 HTML5 全面发展并且我不必支持旧版浏览器在我的应用程序中!

【讨论】:

只是好奇,你为什么不把[webtoolkit.info/javascript-base64.html#],然后注释掉input = Base64._utf8_encode(input);output = Base64._utf8_decode(output);?除了utf-8转换错误还有什么问题吗? @shr 我不知道如何在每个浏览器中获取二进制文件数据以输入到这些方法中? $('#inputid').files[0](在 IE7 中不起作用,据我所知)。如果有那么容易? var output = Base64.encode($('#inputid').files[0])??【参考方案3】:

在自己为此苦苦挣扎之后,我开始为支持它的浏览器(Chrome、Firefox 和尚未发布的 Safari 6)实现 FileReader,以及一个将 POST 文件数据回显为 Base64 编码数据的 php 脚本对于其他浏览器。

【讨论】:

【参考方案4】:

我使用 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();
);

【讨论】:

【参考方案5】:

我的解决方案是在其结果上使用 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');
    ;

【讨论】:

到目前为止最简单的方法,为什么没有更多的选票?【参考方案6】:

受@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)

【讨论】:

【参考方案7】:

完整示例

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 的回答。

以上是关于从输入表单中获取 Base64 编码文件数据的主要内容,如果未能解决你的问题,请参考以下文章

从 PEM BASE64 编码的私钥文件中获取 RSA 私钥

在 laravel 中解码和移动 base64 编码的图像

如何从 base 64 编码字符串中获取十六进制块?

用的ajax提交的表单,js base64编码怎么用

base64加密linux去除分隔符

前台js获取base64编码显示图片,明明获取到值,但是报错提示src不能为undefined,在线等!跪求大佬!!!