UrlFetchApp下载文件被截断至20MB,如何解决该问题?
Ah, I've run into this exact issue before! The problem here is that UrlFetchApp has a default response size limit of 20MB—that's why your 150MB file gets chopped off mid-download. Let's fix this with two reliable approaches:
方法1:使用Drive高级服务直接导入(推荐)
This method skips loading the entire file into memory entirely, letting Google Drive pull the file directly from your target URL—no 20MB restriction (as long as you have enough Drive storage). Here's how to set it up:
Enable the Drive Advanced Service in your Apps Script project:
- Open the script editor, click
Resources>Advanced Google Services - Find
Drive API, toggle the switch on, then clickOK
- Open the script editor, click
Replace your existing code with this:
const fileUrl = "https://example.com/My150mbFile.dat"; const fileName = "My150mbFile.dat"; // Customize this if you want // Use Drive API to import the file directly from the URL const fileMetadata = { title: fileName }; const media = { mimeType: "application/octet-stream", // Adjust this to match your file type (e.g., "image/png") body: UrlFetchApp.fetch(fileUrl, { muteHttpExceptions: true }) }; const createdFile = Drive.Files.insert(fileMetadata, media, { convert: false // Keep the original file format, no auto-conversion }); console.log("File created successfully. ID: " + createdFile.id);
This works because the Drive API streams the file content instead of loading it all into the Apps Script runtime, which bypasses the UrlFetchApp size limit.
方法2:分块下载并拼接(备用方案)
If you can't enable the Drive Advanced Service for some reason, you can download the file in 20MB chunks (the max single response size for UrlFetchApp) and stitch them together:
const fileUrl = "https://example.com/My150mbFile.dat"; const fileName = "My150mbFile.dat"; const chunkSize = 20 * 1024 * 1024; // 20MB per chunk // First, get the total file size const headResponse = UrlFetchApp.fetch(fileUrl, { method: "HEAD", muteHttpExceptions: true }); const fileSize = parseInt(headResponse.getHeaders()["Content-Length"], 10); let chunks = []; for (let start = 0; start < fileSize; start += chunkSize) { const end = Math.min(start + chunkSize - 1, fileSize - 1); const response = UrlFetchApp.fetch(fileUrl, { headers: { "Range": `bytes=${start}-${end}` }, muteHttpExceptions: true }); chunks.push(response.getBlob().getBytes()); } // Combine all chunks into a single blob const fullBytes = [].concat(...chunks); const fullBlob = Utilities.newBlob(fullBytes, "application/octet-stream", fileName); const createdFile = DriveApp.createFile(fullBlob); console.log("File created successfully. Size: " + createdFile.getSize() + " bytes");
Note: This requires the target server to support Range requests (most modern servers do). If the server doesn't support range headers, this method won't work.
I'd go with Method 1 whenever possible—it's cleaner and avoids any potential issues with range requests. Let me know if you need help getting the Drive API set up!
内容的提问来源于stack exchange,提问作者kevc45

