如何在客户端使用“文件类型”NPM 模块?

疯姜

我正在尝试使用“文件类型”NPM 模块(我在服务器上工作)客户端在文件上传到 S3 存储桶之前验证 MIME 类型。

模块自述文件包括在浏览器中使用它的示例:

const FileType = require('file-type/browser');

const url = 'https://upload.wikimedia.org/wikipedia/en/a/a9/Example.jpg';

(async () => {
    const response = await fetch(url);
    const fileType = await FileType.fromStream(response.body);

    console.log(fileType);
    //=> {ext: 'jpg', mime: 'image/jpeg'}
})();

由于“需要”,这显然不能直接在浏览器中工作,如果我直接链接到 NPM 文件,我会得到:

Uncaught ReferenceError: require is not defined

所以我尝试使用 Webpack(我根本不精通它,但遵循官方 Webpack 教程和其他一些教程)创建一个“main.js”文件,然后通过脚本标签访问它.

例如,通过 Webpack 运行它:

import * as mimeFromBuffer  from 'file-type/browser.js';

export function mimeTyping(mimeValidationBytes){
    (async () => {
        const fileType = await mimeFromBuffer(mimeValidationBytes);
        console.log(fileType);
        //=> {ext: 'jpg', mime: 'image/jpeg'}
    })();
    return;
}

当我调用mimeTyping客户端时,结果如下

Uncaught ReferenceError: mimeTyping is not defined

在浏览器中从这个问题尝试了 Vinay 的回答

import fileType from 'file-type'; 

const blob = file.slice(0, fileType.minimumBytes);

const reader = new FileReader();
reader.onloadend = function(e) {
  if (e.target.readyState !== FileReader.DONE) {
    return;
  }

  const bytes = new Uint8Array(e.target.result);
  const { ext, mime } = fileType.fromBuffer(bytes);

  // ext is the desired extension and mime is the mimetype
};
reader.readAsArrayBuffer(blob);

这让我明白:

Uncaught SyntaxError: Cannot use import statement outside a module

我对这个错误进行了一些研究,一个常见的解决方案是添加"type":"module"package.json. 这没有帮助(错误没有改变)。

在模块的 Github 存储库中发现了一个类似的问题,它表明:

虽然这个模块主要是为 Node.js 设计的,但也可以在浏览器中使用它。这确实是“文件类型/浏览器”的目的所在。它为 JavaScript 模块捆绑器提供了正确的依赖项和正确的功能。一些依赖项,通常存在于 Node.js 环境中,但在浏览器环境中缺失,您可能需要将 (polyfill) 传递给您的模块打包器。尽管在某些情况下配置它可能有点棘手,但请注意,这是由模块捆绑器处理的一项非常常见的任务。

我正在努力理解接下来的步骤是什么。

该线程底部的另一条评论表明作者在以下方面取得了成功:

import { fromBuffer } from 'file-type/core';
...
const buffer = await uploadedFile.arrayBuffer();
const types = await fromBuffer(buffer);

我不确定如何实现它,以及我需要什么其他代码(我猜这会传递给 Webpack,并且可能需要一个export语句,然后是import客户端?)

我试过将其传递给 Webpack:

const fileType = require('file-type/browser');

module.exports = fileType;

但是再次链接到输出文件会得到:

Uncaught SyntaxError: Cannot use import statement outside a module

我从概念上理解我需要做什么:将 NPM 模块传递给 Webpack,Webpack 反过来解析它并找到任何依赖项,获取这些依赖项,并创建一个我可以在客户端使用的 JavaScript 文件。看来我在那里做错了什么。

我花了几天时间试图了解如何使用 NPM 模块客户端(在我的脑海中仍然很模糊)并尝试了上述代码的各种变体 - 非常感谢一些指导(第一次在这里发布问题 - 请放轻松在我身上!)。

谢谢!

编辑:我不认为这是重复的 - 我确实回顾了如何从 node_modulesMeteor Npm -module client-side导入 JS 库如何在客户端使用 node.js 模块系统如何在客户端机器上使用客户端 JavaScriptNode Js 应用程序调用服务器端 NodeJS 函数但我尝试过的任何建议似乎都没有帮助。

疯姜

终于得到了这个工作。万一其他人被困在这个问题上,这里有一个解释(为缺乏简洁而道歉 - 可能这应该是一篇博客文章......)。

为了进一步充实用例,我使用Uppy来允许用户将文件上传到 AWS S3 存储桶。它的工作方式是,当用户上传文件时,Uppy 会调用我的服务器,在那里生成 AWS 预签名 URL 并将其传递回客户端。然后,客户端使用该预签名 URL 将文件直接上传到 S3 存储桶,绕过服务器,这样文件在任何时候都不会通过服务器。

我试图解决的问题是缺少扩展名的文件最终上传的内容/MIME 类型设置为“应用程序/八位字节”,因为浏览器、Uppy 和 S3 似乎都依赖文件扩展名来决定文件类型(而不是解析文件的所谓“魔术字节”),如果缺少文件扩展名,AWS 默认为“application/octet”。当用户尝试打开文件时,这会导致问题,因为它们没有得到正确处理(即没有扩展名且具有“应用程序/八位字节”内容/MIME 类型的 png 文件打开下载对话框而不是被预览等)。我还想在扩展名存在的情况下验证 MIME 类型/文件类型,以便我可以排除某些类型的文件,

我使用“文件类型”NPM 模块来确定 mimetype 服务器端,这很简单,但是在生成 AWS 预签名 URL 时更改文件的内容类型/MIME 类型不足以解决问题 - 它仍然被上传为“应用程序/八位字节”。我想使用相同的模块客户端,因此我们在客户端上获得与在服务器上完全相同的结果,并且在任何情况下都需要确定 MIME 类型并相应地设置它在上传前但预签名后的 URL。我不知道如何做到这一点(即使用“文件类型”客户端 - 我的问题的核心)。

我终于放弃了 Webpack - 我尝试过的一切都不奏效。所以我切换到 Browserify,“文件类型”存储库中的示例浏览器代码立即生效!因此,我不得不试图弄清楚如何通过 Browserify 传递一个函数以在客户端代码中使用。

这对我来说是不可能的 - 我不知道如何将异步 IIFE 传递给我的代码。因此,我将我的 Uppy 代码移动到我传递给 Browserify 的代码中:

// Get the dependency, which we've added to node via "npm install file-type":
const FileType = require('file-type/browser');

// When the user adds a file for upload to Uppy...
uppy.on('file-added', (file) => {
    
    // 1. Create a filereader:
    const filereader = new FileReader();
    
    filereader.onloadend = function(evt) {
        
        // 4. Once the filereader has successfully finished reading the file...
        if (evt.target.readyState === FileReader.DONE) {
            
            // Get the unsigned 8 bit int8Array (ie Uint8Array) of the 600 bytes (this looks like '[119,80,78,71...]'):
            const uint = new Uint8Array(evt.target.result);
       
            // Determine the mime type using the "file-type" NPM package:
            (async () => {
                
                // Pass in our 600 bytes ("uint"):
                const fileType = await FileType.fromBuffer(uint);
            
                console.log(fileType); // outputs => {ext: 'jpg', mime: 'image/jpeg'}
                
                // Do some validation here...
                
                //
                
                //  Assign the results to the file for upload - we're done!:
                file.extension = fileType.ext;
                file.meta.type = fileType.mime;
                file.type = fileType.mime;
            })();
        }
    }
    
    // 2. Grab the first 600 bytes of the file for mime type analysis server side - most mime
    // types use the first few bytes, but some (looking at you, Microsoft...) start at the 
    // 513th byte; ISO CD files start at the 32,770th byte, so we'll ignore those rather than 
    // send that much data for each file - users of this system certainly aren't expected to 
    // upload ISO CD files! Also, some .zip files may start their identifying bytes at the 
    // 29,153nd byte - we ignore those too (mostly, .zip files start at the first, 31st, or 527th byte).
    const blob = file.data.slice(0, 600);        
    
    // 3. Start reading those 600 bytes...continues above at 'filereader.onloadend':
    filereader.readAsArrayBuffer(blob);
})

这一切都进入了一个我称之为“index.js”的文件,然后,通过“npm install -g browserify”在命令行安装了 Browserify,我在命令行中使用它来创建文件(“main.js”)我在客户端代码中链接到:

browserify index.js -o main.js

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何在DENO中使用npm模块?

从哪里开始创建Minecraft客户端模块

如何从不同的模块生成客户端API

如何从应用程序客户端连接远程EJB模块

Kubernetes客户端Go找不到模块

如何修复错误“ AttributeError:'模块'对象在python3中没有属性'客户端'?

如何在客户端代码中使用节点模块?

NPM请求模块(REST客户端)的默认超时是多少?

如何使用瓶颈npm模块

如何使用Gradle使用客户端模块编译Kotlin域模块?

在客户端React组件中导入npm模块

如何在我的Electron应用程序的客户端代码中导入Node模块?

如何仅构建evosuite的客户端模块

如何在不破坏现有客户端的情况下扩展terraform模块输入变量模式?

使用node.js中的soap模块在客户端中添加soap标头

用于node.js的hazelcast客户端模块

Perl REST客户端模块-如何在更新后恢复整个JSON

适用于PHP的oAuth客户端模块

如何在通过CasperJS运行的文件中使用NPM模块?

如何从ubuntu 16.04内核客户端和内核模块中删除nvidia驱动程序,或使内核clent和模块使用相同的nvidia驱动程序?

结合使用节点模块和汇总来构建Web客户端

NPM:更新模块中的模块

如何在模块中使用模块

Python:ModuleNotFoundError:没有名为“客户端”的模块

如何通过@NAmdConfig 为客户端脚本使用相对模块路径?套件脚本 2.0

在模块内播放 WS 客户端

在 nodeJs 的其他模块中使用 Redis 客户端实例

使用物联网集线器边缘模块客户端获取设备孪生属性

使用 ExpressJS,如何在客户端使用 NPM 包?