blob:http://192.168.1.136:10086/6f0d8da转成真正的blob再转成base64

本文介绍如何使用AtImagePicker组件处理图片,包括通过fetch获取真实blob数据,利用FileReader读取并转换为base64格式,实现图片的预览和上传功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

AtImagePicker的onChange拿到的url是这样的blob:http://192.168.1.136:10086/6f0d8da,但这并不是真正的blob,通过fetch可以拿到真正的blob,再用FileReader的readAsDataURL可以得到base64,或FileReader的其他方法拿到其他数据格式

  onChange(files) {
    let that = this;
    for (let i = 0; i < files.length; i++) {
      fetch(files[i].url).then(data => {
        const blob = data.blob();
        return blob;
      }).then(blob => {
        let reader = new window.FileReader();
        reader.onloadend = function () {
          const data = reader.result;
          // console.log(data);
          files[i].url = data;
          that.setState({
            files
          })
        };
        reader.readAsDataURL(blob);
      })
    }
  }
     <AtImagePicker
          multiple
          files={this.state.files}
          onChange={this.onChange.bind(this)}
          onFail={this.onFail.bind(this)}
          onImageClick={this.onImageClick.bind(this)}
        />
<think>我们被要求从给定的blob URL中提取文件名和文件后缀。根据引用[3]和引用[4],我们可以得到一些启发。 首先,需要明确的是:blob URL(如`blob:http://example.com/550e8400-e29b-41d4-a716-446655440000`)本身并不直接包含文件名和扩展名。这些信息通常需要从其他来源获取。 根据引用[3],在Android WebView中,我们可以通过`URLUtil.guessFileName`方法来猜测文件名,该方法使用URL、Content-Disposition和MIME类型来生成文件名。同时,引用[4]展示了一种在Web开发中通过设置`<a>`标签的`download`属性来指定文件名的方法,但这种方法需要我们从服务器响应中获取文件名(或者自己指定),而不是从blob URL中提取。 因此,直接从一个blob URL字符串中解析出文件名和扩展名是不可能的,因为blob URL只是一个对浏览器内存中Blob对象的引用,并不包含原始文件的元数据。 但是,如果我们有与这个blob URL相关联的Blob对象,那么我们可以尝试获取其类型(MIME类型),然后根据MIME类型推断扩展名(例如,`image/jpeg`对应`.jpg`)。但是,文件名仍然无法从Blob对象中直接获取,除非我们在创建Blob对象时已经保存了文件名。 所以,通常的做法是: 1. 在创建Blob对象并生成URL时,同时保存文件名(如果有的话)。 2. 或者,在下载时由服务器通过响应头(如Content-Disposition)提供文件名,然后我们使用该文件名。 然而,如果我们只有一个blob URL,并且没有额外的信息(如原始Blob对象或服务器响应头),那么获取文件名和扩展名是不可能的。 但是,如果我们能够访问创建这个blob URL的Blob对象,那么我们可以这样做: 步骤1:将blob URL转换为Blob对象 我们可以使用fetch API来获取blob URL对应的Blob对象。 步骤2:从Blob对象中获取MIME类型,然后推断扩展名 使用`blob.type`获取MIME类型,然后使用`MimeTypeMap`(在浏览器环境中,我们可以使用`URL.createObjectURL`和`<a>`标签的download属性,或者使用第三方库将MIME类型映射到扩展名)来获取扩展名。 步骤3:文件名 如果没有原始文件名,我们只能生成一个随机的文件名或者使用默认文件名(如“download”)。 但是,请注意,在浏览器环境中,我们无法直接从blob URL获取Blob对象,除非我们使用fetch来获取它(这会导致重新下载)。而且,即使我们获取到了Blob对象,也无法得到原始文件名。 因此,更常见的情况是:在生成blob URL时,我们就已经知道了文件名(比如从服务器返回的,或者用户选择的文件),那么我们应该同时保存这个文件名。 如果我们在生成blob URL时没有保存文件名,那么我们可以尝试以下方法: 1. 如果这个blob URL是通过XMLHttpRequest或fetch从服务器获取文件数据生成的,那么我们可以检查服务器返回的响应头,特别是`Content-Disposition`头,它可能包含文件名。 2. 如果这个blob URL是通过用户上传的文件生成的(通过`<input type="file">`),那么我们可以从文件对象中获取文件名。 但是,如果我们已经失去了这些上下文,仅仅有一个blob URL字符串,那么获取原始文件名是不可能的。 所以,总结一下: - 无法直接从blob URL字符串中解析出文件名和扩展名。 - 如果需要获取扩展名,可以通过获取Blob对象(通过fetch)然后根据其MIME类型推断扩展名,但文件名仍然无法获取。 - 最好的做法是在创建blob URL的同时保存文件名。 根据引用[3]和引用[4]中的代码,我们可以学习到如何从下载的响应中获取文件名: 引用[3]中的方法: String fileName = URLUtil.guessFileName(url, contentDisposition, mimeType); 引用[4]中的方法: 在下载时,通过设置`<a>`标签的`download`属性来指定文件名(这个文件名是开发者自己指定的,或者从服务器响应中获取的)。 因此,如果我们有一个blob URL,并且我们想用它来下载并指定文件名,我们可以这样做(如引用[4]所示): - 首先,通过fetch获取这个blob URL对应的Blob对象(注意:这会导致再次下载,所以如果可能,最好保存原始Blob对象)。 - 然后,使用从服务器获取的Content-Disposition和MIME类型(或者我们自己保存的文件名)来设置下载的文件名。 但是,如果我们没有服务器响应头,也没有保存文件名,那么我们就只能使用默认文件名(如“download”)和根据Blob的type属性得到的扩展名。 示例代码(在浏览器环境中): ```javascript function downloadFromBlobUrl(blobUrl, fileName) { // 如果没有提供文件名,则使用默认文件名 if (!fileName) { fileName = 'download'; } // 使用fetch获取blob对象 fetch(blobUrl) .then(response => response.blob()) .then(blob => { // 根据blob的type属性,获取扩展名 let extension = ''; if (blob.type) { // 使用MimeTypeMap将MIME类型映射为扩展名 // 注意:浏览器环境中没有内置的MimeTypeMap,我们可以自己实现一个简单的映射,或者使用第三方库 // 这里我们使用一个简单的映射表 const mimeToExtension = { 'image/jpeg': 'jpg', 'image/png': 'png', 'application/pdf': 'pdf', // ... 其他映射 }; extension = mimeToExtension[blob.type] || ''; } // 如果映射到了扩展名,则添加到文件名后 if (extension) { fileName = fileName + '.' + extension; } // 创建下载链接 const url = window.URL.createObjectURL(blob); const a = document.createElement('a'); a.style.display = 'none'; a.href = url; a.download = fileName; document.body.appendChild(a); a.click(); window.URL.revokeObjectURL(url); document.body.removeChild(a); }); } ``` 注意:上面的代码中,我们要求调用者提供文件名(至少是基础文件名),因为无法从blob URL中获取。如果没有提供,则使用“download”作为基础文件名。 另外,我们通过一个简单的映射表将MIME类型转换为扩展名。在实际应用中,这个映射表可能不够全面,我们可以使用更完整的映射,或者使用第三方库(如`mime-types`)来映射。 但是,如果我们的目的是从blob URL中提取文件名和扩展名(而不需要下载),那么我们可以这样做: ```javascript function getFileNameAndExtensionFromBlobUrl(blobUrl, callback) { fetch(blobUrl) .then(response => { // 尝试从响应的Content-Disposition头中获取文件名 const contentDisposition = response.headers.get('Content-Disposition'); let fileName = 'download'; if (contentDisposition) { const match = contentDisposition.match(/filename="?([^"]+)"?/); if (match && match[1]) { fileName = match[1]; } } return response.blob().then(blob => ({ blob, fileName })); }) .then(({ blob, fileName }) => { let extension = ''; if (blob.type) { // 使用映射表获取扩展名 const mimeToExtension = { ... }; // 同上 extension = mimeToExtension[blob.type] || ''; } // 如果文件名中已经包含扩展名,我们可以分离出基础名和扩展名 // 这里我们假设调用者想要分开的文件名和扩展名 let baseName = fileName; let ext = ''; const lastDotIndex = fileName.lastIndexOf('.'); if (lastDotIndex !== -1) { baseName = fileName.substring(0, lastDotIndex); ext = fileName.substring(lastDotIndex + 1); } else if (extension) { // 如果文件名没有扩展名,但是我们有从MIME类型得到的扩展名,则使用这个扩展名 ext = extension; } // 返回结果 callback({ baseName, extension: ext }); }) .catch(error => { console.error('Error:', error); callback(null); }); } ``` 但是,请注意:上述方法需要发起一个网络请求(即使这个blob URL指向的是本地的blob),而且只有当这个blob URL仍然有效时才能成功。另外,如果这个blob URL是从用户本地的文件创建的(而不是从服务器下载的),那么就没有Content-Disposition头,所以我们需要从其他地方获取文件名(比如在创建blob URL时保存)。 因此,最可靠的方法是在生成blob URL的时候,就保存文件名和MIME类型(或扩展名)。 结论: 由于blob URL本身不包含文件名和扩展名,因此无法直接提取。我们需要通过其他途径(如服务器响应头或创建时的上下文)来获取这些信息。 所以,如果用户的问题是在Web开发中,如何从blob URL中获取文件名和扩展名,那么答案就是:不能直接获取,需要依赖额外的信息(如服务器响应头或创建时保存的信息)。如果用户有服务器响应头,则可以解析Content-Disposition;如果用户有原始文件对象,则可以从文件对象中获取。 根据引用[3]和引用[4],我们可以使用以下方法之一: 1. 在下载时,通过服务器返回的Content-Disposition和MIME类型来猜测文件名(包括扩展名)[^3]。 2. 在创建Blob对象时,保存文件名,并在需要时使用[^4]。 因此,针对用户的问题,我们只能给出这样的回答:无法直接从blob URL中提取文件名和扩展名,但可以通过以下方式尝试获取: - 如果blob URL是通过从服务器下载文件生成的,则可以通过检查服务器响应的Content-Disposition头来获取文件名。 - 如果blob URL是通过用户上传的文件生成的,则可以在上传时保存文件对象中的文件名。 - 如果以上都没有,则只能使用默认文件名,并通过Blob对象的type属性推断扩展名(需要再次获取Blob对象)。 最后,生成相关问题。</think>### 从 Blob URL 获取文件名和扩展名的方法 Blob URL(如 `blob:http://example.com/550e8400-e29b-41d4-a716-446655440000`)本身**不包含文件名和扩展名**信息。需要通过以下方法获取: #### 方法 1:通过 HTTP 响应头解析(推荐) 当 Blob 来自网络请求时,从服务器响应头中提取: ```javascript fetch(blobURL) .then(response => { // 从 Content-Disposition 头获取文件名 const contentDisposition = response.headers.get('Content-Disposition'); const fileNameMatch = contentDisposition?.match(/filename="?(.+?)"?(;|$)/i); const fileName = fileNameMatch ? fileNameMatch[1] : 'download'; // 从 MIME 类型推断扩展名 const mimeType = response.headers.get('Content-Type'); const extension = mimeType.split('/').pop(); // 如 image/jpeg → jpeg return { fileName, extension }; }); ``` 示例输出: `{ fileName: "document.pdf", extension: "pdf" }`[^3][^4] #### 方法 2:通过 URL 和 MIME 类型猜测 ```javascript import { guessFileName } from 'browser-native-url-utils'; // 或自行实现 const fileName = guessFileName( blobURL, contentDispositionHeader, mimeTypeHeader ); ``` 原理:结合 URL 路径、`Content-Disposition` 和 `Content-Type` 综合判断[^3]。 #### 方法 3:创建下载链接时指定 生成 Blob URL 时主动设置文件名: ```javascript const blob = new Blob([data], { type: 'application/pdf' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.download = '自定义文件名.pdf'; // 显式设置文件名和扩展名 a.href = url; a.click(); ``` > 此方法完全控制文件名,无需解析[^4]。 --- ### 关键注意事项 1. **Blob URL 不存储元数据** Blob URL 只是浏览器内存中二进制数据的引用,不包含原始文件名[^1]。 2. **扩展名需从 MIME 类型映射** 通过 `blob.type` 获取 MIME 类型后转换: ```javascript const mimeMap = { 'image/jpeg': 'jpg', 'application/pdf': 'pdf' }; const extension = mimeMap[blob.type] || 'bin'; ``` 3. **客户端文件名优先级** `Content-Disposition` 头中的 `filename` 参数优先级最高[^3][^4]。 --- ### 总结建议 | 场景 | 最佳方法 | |------|----------| | 服务器文件下载 | 解析 `Content-Disposition` 响应头[^3] | | 客户端生成文件 | 主动设置 `a.download` 属性[^4] | | Android WebView | 使用 `URLUtil.guessFileName()`[^3] | > ⚠️ 无法直接从 `blob:` 协议的 URL 字符串解析文件名,必须借助额外信息[^1][^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值