当前位置: 首页 > news >正文

vue 移动端app预览和保存pdf踩坑

需求

使用Vue开发h5,嵌套到Android和IOS的Webview里,需要实现pdf预览和保存功能,预览pdf的功能,我这边使用了三个库,pdf5,pdf.js,vue.pdf,现在把这三个库在app端的坑分享一下。先说预览的,保存的实现等会再说

前置条件

用第三方库访问pdf,很可能会出现跨域的问题,这个需要后端来处理一下。具体怎么处理,自行百度。我用pdf.js访问的时候,尝试过前端解决跨域,可以参考一下

pdf5实现

先说pdf,这个集成和实现都很简单,但是有个问题,页数多的话,一直现在加载中,并不能加载成功,始终在第一页,这个问题暂时没解决,有大佬知道的话可以指点一下

<template><div style="height: 100vh"><div id="pdf-content" style="height: 60vh"></div><div class="div-task-button"><div class="tasks-button" @click="downloadPdf">保存</div></div></div></div>
</template>// import Pdfh5 from "pdfh5";
// import "pdfh5/css/pdfh5.css";
import pdf from "vue-pdf";
export default {name: "Pdfh5",data() {return {pdfh5: null,title: "通知单",pdfUrl: "", // 如果引入本地pdf文件,需要将pdf放在public文件夹下,引用时使用绝对路径(/:表示public文件夹)};},mounted() {try {let orderItem = JSON.parse(this.$route.query.item);this.title = orderItem.title;this.pdfUrl = orderItem.pdfUrl ;} catch (e) {console.log(e)}this.initPdf();},methods: {initPdf() {this.pdfh5 = new Pdfh5("#pdf-content", {pdfurl: this.pdfUrl, // pdf 地址,请求的地址需要为线上的地址,测试的本地的地址是不可以的lazy: true, // 是否懒加载withCredentials: true,renderType: "svg",maxZoom: 3, //手势缩放最大倍数 默认3scrollEnable: true, //是否允许pdf滚动zoomEnable: true, //是否允许pdf手势缩放});},downloadPdf() {console.log("开始下载");let body = {url: this.pdfUrl,};if (config.isAndroid && window.hesAndroidNative) {window.hesAndroidNative.openSystemBrowser(JSON.stringify(body));} else if (config.isIos && window.webkit) {window.webkit.messageHandlers.openSystemBrowser.postMessage(JSON.stringify(body));} else {}},},
};
</script>

pdf.js 实现

使用pdf.js实现,需要下载文件包,具体实现参考
vue开发h5页面如何使用pdf.js实现预览pdf

<template><div style="height: 100vh"><iframe id="pdfViewer" title="" width="100%" height="60%"></iframe><div class="div-task-button"><div class="tasks-button" @click="downloadPdf">保存</div></div></div></div>
</template>
<script>export default {name: "Pdfh5",data() {return {pdfh5: null,title: "通知单",numPages: undefined,// 可引入网络文件或者本地文件pdfUrl: "", // 如果引入本地pdf文件,需要将pdf放在public文件夹下,引用时使用绝对路径(/:表示public文件夹)};},mounted() {try {let orderItem = JSON.parse(this.$route.query.item);this.title = orderItem.title;this.pdfUrl = orderItem.pdfUrl;} catch (e) {console.log(e)}const pdfLink = '/web/viewer.html?file=' + encodeURIComponent( this.pdfUrl);document.getElementById('pdfViewer').src = pdfLink;// fetch(this.pdfUrl, {//   method: "get",//   mode: "no-cors", //防止跨域//   responseType: "blob",// })//   .then((response) => response.blob())//   .then((blob) => {//     const blobUrl = URL.createObjectURL(blob);//     console.log("blobUrl", blobUrl);//      const pdfLink = '/web/viewer.html?file=' + encodeURIComponent(blobUrl);//      document.getElementById('pdfViewer').src = pdfLink;//   });//this.initPdf();},methods: {},downloadPdf() {console.log("开始下载");let body = {url: this.pdfUrl,};if (config.isAndroid && window.hesAndroidNative) {window.hesAndroidNative.openSystemBrowser(JSON.stringify(body));} else if (config.isIos && window.webkit) {window.webkit.messageHandlers.openSystemBrowser.postMessage(JSON.stringify(body));} else {}// this.pdfh5.download("体检通知单");},},
};
</script>

刚开始呢,也是遇到了跨域,我想着看看前端能不能处理,先把url转成blob,然后在用pdf.js来加载blob,就是注释掉的那几行代码

  fetch(this.pdfUrl, {method: "get",mode: "no-cors", //防止跨域responseType: "blob",}).then((response) => response.blob()).then((blob) => {const blobUrl = URL.createObjectURL(blob);console.log("blobUrl", blobUrl);const pdfLink = '/web/viewer.html?file=' + encodeURIComponent(blobUrl);document.getElementById('pdfViewer').src = pdfLink;});

这么说吧,可以实现,但是又出现了另一个问题,因为使用iframe,Refused to display 'http://192.xxxxxx/' in a frame because it set 'X-Frame-Options' to 'deny'.,这个又需要后台配置
参考文章
VUE使用 iframe 嵌入网页,浏览器报错 x-frame-options deny

这是通义千问上给出的跨域答案,可以作为参考:

PDF.js在加载和渲染远程PDF文件时,如果文件所在的服务器与应用所在服务器不是同一个源(即存在跨域问题),会受到浏览器同源策略的限制,从而导致无法正确加载和显示PDF文件。以下是几种处理PDF.js跨域问题的方法:

  1. 服务器端代理

    • 在后端服务中处理跨域问题,比如在Django等后端框架中,你可以创建一个API接口,这个接口负责从远程服务器获取PDF文件,然后将文件内容作为流返回给前端,绕过浏览器的同源策略。

StreamingHttpResponse import requests

def serve_pdf(request):
# 获取远程PDF文件
response = requests.get(‘http://remote-server.com/path/to/file.pdf’, stream=True)
# 设置响应头,允许跨域等
response_headers = response.headers
response_headers[‘Access-Control-Allow-Origin’] = ‘*’
return StreamingHttpResponse(response.iter_content(chunk_size=1024),
content_type=response.headers[‘Content-Type’],
headers=response_headers) ```

  1. CORS配置

    • 如果你控制远程服务器,可以在服务器上配置CORS(Cross-Origin Resource Sharing)。例如,在Nginx或Apache服务器上,可以通过添加响应头Access-Control-Allow-Origin来允许特定源或者所有源访问资源。
        if ($request_method = 'OPTIONS') {add_header 'Access-Control-Allow-Origin' '*';add_header 'Access-Control-Allow-Methods' 'GET';add_header 'Access-Control-Allow-Headers' 'Range';add_header 'Access-Control-Max-Age' 1728000;add_header 'Content-Type' 'text/plain charset=UTF-8';add_header 'Content-Length' 0;return 204;}if ($request_method = 'GET') {add_header 'Access-Control-Allow-Origin' '*';}try_files $uri $uri/ =404;    }    ```
  2. 修改PDF.js自身行为

    • PDF.js可以通过修改其内部的网络请求模块来发送跨域请求,并且处理相关的预检请求(OPTIONS)以符合CORS规范。
    • 有时可能需要移除或修改代码中对跨域错误处理的部分,但这并不是推荐做法,因为这可能导致安全风险。
  3. Blob URL或FileReader API

    • 可以在客户端JavaScript中利用fetch或其他手段获取远程PDF文件,然后创建一个Blob对象,再将其转换为Blob URL,之后传递给PDF.js viewer。
      .then(response => response.blob())
      .then(blob => {
      const blobUrl = URL.createObjectURL(blob);
      const pdfLink = '/web/viewer.html?file=' + encodeURIComponent(blobUrl);
      document.getElementById('pdfViewer').src = pdfLink;
      });    ```

根据具体场景选择合适的解决方案,优先推荐配置服务器端的CORS策略,其次是通过后端代理转发请求。同时,请确保遵循相关安全原则,避免因放宽跨域策略而引入的安全隐患。

使用vue-pdf实现

最好使用

cnpm install vue-pdf@4.3.0

安装,防止报错,这个实现也简单

<template><div style="height: 100vh"><!-- <div id="pdf-content" style="height: 60vh"></div> --><!-- <iframe id="pdfViewer" title="" width="100%" height="60%"></iframe> --><div class="pdf_wrap"><div class="pdf_list"><pdfv-for="i in numPages":key="i":src="pdfUrl":page="i"style="display: inline-block; width: 100%"></pdf></div><div class="div-task-button"><div class="tasks-button" @click="downloadPdf">保存</div></div></div></div>
</template>
<script>
// import Pdfh5 from "pdfh5";
// import "pdfh5/css/pdfh5.css";
import pdf from "vue-pdf";
export default {name: "Pdfh5",components: {pdf,},data() {return {pdfh5: null,title: "通知单",numPages: undefined,// 可引入网络文件或者本地文件pdfUrl: "", // 如果引入本地pdf文件,需要将pdf放在public文件夹下,引用时使用绝对路径(/:表示public文件夹)};},mounted() {try {let orderItem = JSON.parse(this.$route.query.item);this.title = orderItem.title;this.pdfUrl = pdf.createLoadingTask(orderItem.pdfUrl);console.log(" this.pdfUrl", this.pdfUrl);this.pdfUrl.promise.then((pdf) => {this.numPages = pdf.numPages;})} catch (e) {console.log(e)}// const pdfLink = '/web/viewer.html?file=' + encodeURIComponent( this.pdfUrl);// document.getElementById('pdfViewer').src = pdfLink;// fetch(this.pdfUrl, {//   method: "get",//   mode: "no-cors", //防止跨域//   responseType: "blob",// })//   .then((response) => response.blob())//   .then((blob) => {//     const blobUrl = URL.createObjectURL(blob);//     console.log("blobUrl", blobUrl);//      const pdfLink = '/web/viewer.html?file=' + encodeURIComponent(blobUrl);//      document.getElementById('pdfViewer').src = pdfLink;//   });//this.initPdf();},methods: {initPdf() {this.pdfh5 = new Pdfh5("#pdf-content", {pdfurl: this.pdfUrl, // pdf 地址,请求的地址需要为线上的地址,测试的本地的地址是不可以的lazy: true, // 是否懒加载withCredentials: true,renderType: "svg",maxZoom: 3, //手势缩放最大倍数 默认3scrollEnable: true, //是否允许pdf滚动zoomEnable: true, //是否允许pdf手势缩放});},downloadPdf() {console.log("开始下载");let body = {url: this.pdfUrl,};if (config.isAndroid && window.hesAndroidNative) {window.hesAndroidNative.openSystemBrowser(JSON.stringify(body));} else if (config.isIos && window.webkit) {window.webkit.messageHandlers.openSystemBrowser.postMessage(JSON.stringify(body));} else {}// this.pdfh5.download("体检通知单");},},
};
</script>
<style scoped>
.pdf_wrap {background: #fff;height: 90vh;
}
.pdf_list {height: 65vh;overflow: scroll;
}
.div-task-button {display: flex;align-items: center;width: 100%;justify-content: center;
}
.tasks-button {display: flex;background: white;padding-bottom: 10px;padding-top: 10px;border-radius: 20px;border: 1px solid #4a90e2;justify-content: center;color: #4a90e2;font-size: 16px;margin: 80px 20px;width: 100%;font-weight: 600;
}
</style>

但是运行起来会有问题,

Cannot read properties of undefined (reading ‘catch’)

这个是版本的问题,需要修改源码,要把node_modules\vue-pdf\src\pdfjsWrapper.js中第196行注释掉

//注释掉catch,防止出现Cannot read properties of undefined (reading ‘catch’)
// pdfRender.cancel().catch(function(err) {
// emitEvent(‘error’, err);
// });–>

保存pdf

在pc端很好实现了,但是嵌入到移动端的webview中,包括IOS和android的兼容性之类的问题,不太好实现,最简单的饿一个办法就是Js调用原生app的方法,打开默认浏览器,用浏览器去保存
js方法呢,就是这一段

  downloadPdf() {console.log("开始下载");let body = {url: this.pdfUrl,};if (config.isAndroid && window.hesAndroidNative) {window.hesAndroidNative.openSystemBrowser(JSON.stringify(body));} else if (config.isIos && window.webkit) {window.webkit.messageHandlers.openSystemBrowser.postMessage(JSON.stringify(body));} else {}// this.pdfh5.download("体检通知单");},

android端的实现方法呢,就是

 //打开系统浏览器@JavascriptInterfacepublic void openSystemBrowser(String param) {Gson gson = new Gson();Map<String,String> map = gson.fromJson(param, Map.class);String url = map.get("url");Log.e("url",url);Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));if (intent.resolveActivity(getPackageManager()) != null) {startActivity(intent);} else {// 没有可用的浏览器应用程序Toast.makeText(WebviewBase.this, "没有可用的浏览器应用程序", Toast.LENGTH_SHORT).show();}}

相关文章:

vue 移动端app预览和保存pdf踩坑

需求 使用Vue开发h5&#xff0c;嵌套到Android和IOS的Webview里&#xff0c;需要实现pdf预览和保存功能&#xff0c;预览pdf的功能&#xff0c;我这边使用了三个库&#xff0c;pdf5&#xff0c;pdf.js&#xff0c;vue.pdf&#xff0c;现在把这三个库在app端的坑分享一下。先说…...

Vueuse:打造高效的 Vue.js 开发利器

Vueuse&#xff1a;打造高效的 Vue.js 开发利器 Vueuse 是一个功能强大的 Vue.js 生态系统工具库&#xff0c;它提供了一系列的可重用的 Vue 组件和函数&#xff0c;帮助开发者更轻松地构建复杂的应用程序。本文将介绍 Vueuse 的主要特点和用法&#xff0c;以及它在 Vue.js 开发…...

mysql锁的创建方式

在 MySQL 中,锁是用来控制多个用户对同一数据的访问。主要有两种类型的锁:表级锁和行级锁。MySQL 的锁定机制主要是通过 SQL 语句来实现的,而不是通过特定的锁定命令。下面是一些常见的锁相关的 SQL 操作方式:表级锁 MySQL 中,表级锁是最基本的锁策略,它会锁定整个表。一…...

5.WEB渗透测试-前置基础知识-常用的dos命令

内容参考于&#xff1a; 易锦网校会员专享课 上一篇内容&#xff1a;4.WEB渗透测试-前置基础知识-快速搭建渗透环境&#xff08;下&#xff09;-CSDN博客 常用的100个CMD指令 1.gpedit.msc—–组策略 2. sndrec32——-录音机 3. Nslookup——-IP地址侦测器 &#xff0c;是一个…...

解决:code ERESOLVE:ERESOLVE could not resolve 的报错问题

报错实例 报错原因 是我执行npm i xxx-xx的时候会出现这个错误 查了资料表示是node.js的问题 或者的依赖本身的问题 解决 1.在后面加上 --legacy-peer-deps 示例&#xff1a;npm i sass-loader7.3.1 --legacy-peer-deps 2&#xff0c;检查node版本&#xff0c;更改node版本 …...

Dockerfile(3) - WORKDIR 指令详解

WORKDIR 切换到镜像中的指定路径&#xff0c;设置工作目录在 WORKDIR 中需要使用绝对路径&#xff0c;如果镜像中对应的路径不存在&#xff0c;会自动创建此目录一般用 WORKDIR 来替代 切换目录进行操作的指令 RUN cd <path> && <do something> WORKDIR…...

2024万元投影仪怎么选?极米RS10 Ultra和当贝X5 Ultra实测横评

随着过去一年投影仪的不断进步&#xff0c;高端型号在2024年初的选择变得更加多样。除了激光外混光已然成为“金字塔顶端”的一种全新光源选择。目前主流的就是作为Dual Light 2.0新升级的极米RS10 Ultra&#xff0c;以及ALPD5.0超级全色激光代表当贝X5 Ultra。很多人也肯定想知…...

java环境搭建

要搭建 Java 环境&#xff0c;你需要进行以下步骤&#xff1a; 1. 下载和安装 JDK&#xff08;Java Development Kit&#xff09;&#xff1a;访问 Oracle 官方网站&#xff08;https://www.oracle.com/java/technologies/javase-jdk14-downloads.html&#xff09;&#xff0c;…...

【GB28181】wvp-GB28181-pro快速修改登录页面名称(前端)

引言 作为一个非前端开发人员,自己摸索起来比较费劲,也浪费了很多时间 本文快速帮助开发者修改为自己名称的一个国标平台 文章目录 一、 预期效果展示二、 源码修改-前端三、 验证修改效果一、 预期效果展示 二、 源码修改-前端 需要修改的文件位置: 项目工程下web_src目录…...

【lv15 day1 设备号申请和注销】

一、Linux内核对设备的分类 linux的文件种类&#xff1a; -&#xff1a;普通文件 d&#xff1a;目录文件 p&#xff1a;管道文件 s&#xff1a;本地socket文件 l&#xff1a;链接文件 c&#xff1a;字符设备 b&#xff1a;块设备Linux内核按驱动程序实现模型框架的不同&#…...

JVM对象创建与内存分配机制

JVM对象创建与内存分配机制 JVM对象创建与内存分配机制 JVM对象创建与内存分配机制对象的创建过程内存分配对象栈上分配对象逃逸分析标量替换 对象在Eden区分配大对象直接进入老年代长期存活的对象将进入老年代对象年龄动态判断老年代空间分配担保机制 对象头与指针压缩对象头利…...

《TCP/IP详解 卷一》第10章 UDP和IP分片

目录 10.1 引言 10.2 UDP 头部 10.3 UDP校验和 10.4 例子 10.5 UDP 和 IPv6 10.6 UDP-Lite 10.7 IP分片 10.7.1 例子&#xff1a;IPV4 UDP分片 10.7.2 重组超时 10.8 采用UDP的路径MTU发现 10.9 IP分片和ARP/ND之间的交互 10.10 最大UDP数据报长度 10.11 UDP服务器…...

Android进阶之路 - RecyclerView停止滑动后Item自动居中(SnapHelper辅助类)

之前一直没注意 SnapHelper 辅助类的功能&#xff0c;去年的时候看到项目中仅通过俩行代码设置 RecyclerView 后就提升了用户体验&#xff0c;觉得还是很有必要了解一下&#xff0c;尝试过后才发现其 PagerSnapHelper、LinearSnapHelper 子类可以作用于不同场景&#xff0c;且听…...

高性能图表组件LightningChart .NET v11.0发布——增强DPI感知能力

LightningChart完全由GPU加速&#xff0c;并且性能经过优化&#xff0c;可用于实时显示海量数据-超过10亿个数据点。 LightningChart包括广泛的2D&#xff0c;高级3D&#xff0c;Polar&#xff0c;Smith&#xff0c;3D饼/甜甜圈&#xff0c;地理地图和GIS图表以及适用于科学&am…...

神经网络系列---计算图基本原理

文章目录 计算图符号微分符号微分的步骤示例符号微分在计算图中的使用总结 数值微分前向差分法中心差分法数值微分的使用注意事项总结 自动微分1. 基本原理2. 主要类型3. 计算图4. 应用5. 工具和库6. 优点和缺点 计算图1. **计算图的建立**2. **前向传播**3. **反向传播**4. **…...

3D数字孪生

数字孪生&#xff08;Digital Twin&#xff09;是物理对象、流程或系统的虚拟复制品&#xff0c;用于监控、分析和优化现实世界的对应物。 这些数字孪生在制造、工程和城市规划等领域变得越来越重要&#xff0c;因为它们使我们能够在现实世界中实施改变之前模拟和测试不同的场景…...

C++惯用法之空基类优化

相关系列文章 C惯用法之Pimpl C惯用法之CRTP(奇异递归模板模式) C之std::tuple(二) : 揭秘底层实现原理 目录 1.空类 2.空基类优化 3.内存布局原则 4.实例分析 5.总结 1.空类 C 中每个对象的实例都可以通过取地址运算符获取其在内存布局中的开始位置&#xff0c;因此每个类…...

【生成式AI】ChatGPT 原理解析(2/3)- 预训练 Pre-train

Hung-yi Lee 课件整理 预训练得到的模型我们叫自监督学习模型&#xff08;Self-supervised Learning&#xff09;&#xff0c;也叫基石模型&#xff08;foundation modle&#xff09;。 文章目录 机器是怎么学习的ChatGPT里面的监督学习GPT-2GPT-3和GPT-3.5GPTChatGPT支持多语言…...

Day03:Web架构OSS存储负载均衡CDN加速反向代理WAF防护

目录 WAF CDN OSS 反向代理 负载均衡 思维导图 章节知识点&#xff1a; 应用架构&#xff1a;Web/APP/云应用/三方服务/负载均衡等 安全产品&#xff1a;CDN/WAF/IDS/IPS/蜜罐/防火墙/杀毒等 渗透命令&#xff1a;文件上传下载/端口服务/Shell反弹等 抓包技术&#xff1a…...

C++多线程同步(上)

多线程同步 引言总述详情互斥锁示例运行结果分析条件变量示例一实现分析优化运行结果示例二实现代码运行结果示例三实现代码运行结果读写锁示例实现代码注意分析运行结果附言实现运行结果运行结果个人心得引言 项目中使用多线程,会遇到两种问题,一种是对共享资源的访问时需要…...

Python的__getattribute__属性

Python中的__getattribute__属性是一个强大而神秘的工具&#xff0c;它隐藏在对象属性访问的背后&#xff0c;默默控制着每一次点号操作的行为。对于想要深入理解Python对象模型的开发者来说&#xff0c;掌握这个特殊方法意味着获得了对属性访问的完全控制权。本文将带您探索__…...

如何快速掌握Comics Downloader:漫画离线阅读的终极解决方案

如何快速掌握Comics Downloader&#xff1a;漫画离线阅读的终极解决方案 【免费下载链接】comics-downloader tool to download comics and manga in pdf/epub/cbr/cbz from a website 项目地址: https://gitcode.com/gh_mirrors/co/comics-downloader 还在为在线漫画加…...

从流水灯到通信协议:深入浅出聊聊移位寄存器在单片机与嵌入式里的那些实用场景

从流水灯到通信协议&#xff1a;深入浅出聊聊移位寄存器在单片机与嵌入式里的那些实用场景 在嵌入式开发的世界里&#xff0c;我们每天都在与各种外设打交道——点亮LED、读取按键、通过串口发送数据。这些看似简单的操作背后&#xff0c;其实隐藏着一套精妙的数字逻辑体系。移…...

绿色极简:一款712KB的快捷回复工具深度解析

在信息交互频繁的当下&#xff0c;客服人员和社群运营者每天都要面对大量重复性咨询。 同样的问候语、同样的产品介绍、同样的售后说明&#xff0c;一天要输入几十甚至上百次。 这种低效的手工重复劳动&#xff0c;不仅消耗大量时间&#xff0c;更容易因疲劳导致错字或遗漏。…...

A1278老将再战:从官方止步High Sierra到OCLP解锁macOS Sequoia的完整指南

1. 为什么选择OCLP而不是Catalina Patcher&#xff1f; 如果你手头有一台2011年末的MacBook Pro A1278&#xff0c;官方支持的最高系统版本是High Sierra&#xff08;10.13&#xff09;。这个系统已经相当老旧&#xff0c;很多现代软件都无法运行。为了解决这个问题&#xff0c…...

SpringBoot测试进阶:JUnit5核心注解实战与高效单元测试设计

1. 为什么你需要掌握JUnit5核心注解 记得去年我接手一个金融项目&#xff0c;第一次看到测试覆盖率要求85%以上的时候&#xff0c;整个人都是懵的。之前在小公司写代码&#xff0c;能跑通就行&#xff0c;哪管什么单元测试。结果第一次代码评审就被打回来十几个测试用例&#x…...

加载时重写 Linux 二进制文件系统调用:低开销控制进程交互的新方法?

在加载时重写 Linux 二进制文件中的每个系统调用问题的起源如今&#xff0c;软件运行方式存在奇怪之处。多数容器&#xff08;生产环境主导部署单元&#xff09;仅运行单个进程&#xff0c;如 Python 脚本、Node.js 服务器或 Go 二进制文件。但此单一进程依赖完整 Linux 内核&a…...

Ubuntu 22.04 LTS 服务器部署 R 与 RStudio Server 全栈指南

1. 为什么选择Ubuntu 22.04 LTS部署R环境&#xff1f; 作为一个长期和数据打交道的科研工作者&#xff0c;我深刻理解在服务器上搭建稳定R环境的重要性。去年接手一个单细胞转录组项目时&#xff0c;本地16GB内存的电脑跑分析直接卡死&#xff0c;这才意识到必须上服务器。Ubu…...

Untrunc终极指南:免费开源视频修复工具,拯救损坏的MP4/MOV文件

Untrunc终极指南&#xff1a;免费开源视频修复工具&#xff0c;拯救损坏的MP4/MOV文件 【免费下载链接】untrunc Restore a truncated mp4/mov. Improved version of ponchio/untrunc 项目地址: https://gitcode.com/gh_mirrors/un/untrunc 你是否曾经遇到过这样的场景&…...

静息态fMRI预处理实战:从DICOM到ALFF的完整流程解析

1. 静息态fMRI预处理入门指南 第一次接触静息态fMRI数据时&#xff0c;我被满屏的DICOM文件搞得晕头转向。这些医学影像数据就像一堆未经整理的拼图碎片&#xff0c;需要我们通过预处理流程将它们转化为可分析的标准化数据。静息态fMRI&#xff08;rs-fMRI&#xff09;记录了大…...