【Vue3】下载zip文件损坏的问题

需求:
需要在vue3上实现Asp.net Web API 下载zip包的功能,本身需求很简单,但是中间遇到了问题,记录一下。

问题:
下载的zip包和后端的zip包大小不一致,后端生成的zip 61kb,下载之后变成了100kb,并且打开就提示损坏,也无法正常解压。

解决:
直接先放后端代码,对外提供接口,返回形式使用FileStreamResult,这个一般不会有问题。

后端代码实现
[HttpPost, Route("downloadalarmexcel")]
public FileStreamResult DownloadAlarmZipFile([FromBody] string mode)
{
    FileStreamResult fileResult = _alarmService.DownloadAlarmZipFile(mode);
    return fileResult;
}
public FileStreamResult DownloadAlarmZipFile(string fileName)
{
    string filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "File", fileName);
    if (!File.Exists(filePath))
    {
        throw new FileNotFoundException("找不到指定的文件", filePath);
    }

    var memory = new MemoryStream();
    using (var stream = new FileStream(filePath, FileMode.Open))
    {
        stream.CopyTo(memory);
    }
    memory.Position = 0;

    return new FileStreamResult(memory, "application/zip")
    {
        FileDownloadName = fileName,
        EnableRangeProcessing = true  // 支持断点续传
    };
}

关键在于前端的文件接收,必须要在请求时加上
responseType: 'blob'
这个如果没有设置下载的文件将出现损坏的问题

// 导出excel
const handleExport = async () => {
    try {
        state.loading = true
        const fileName = 'xxx.zip';
        var AxiosRequestConfig = {
            responseType: 'blob'
        }
        let downloadRes = await getAPI(AlarmApi).apiAlarmDownloadalarmexcelPost(fileName,AxiosRequestConfig) as any;
        // 3. 处理文件下载
        console.log(downloadRes);
        const blob = new Blob([downloadRes.data], { 
            type: 'application/zip;charset=utf-8'
        })
        // 检查blob是否有效
        if (blob.size === 0) {
            throw new Error('文件内容为空')
        }
        const url = window.URL.createObjectURL(blob)
        const link = document.createElement('a')
        link.href = url
        link.download = fileName // 使用服务器返回的文件名
        document.body.appendChild(link)
        link.click()
        document.body.removeChild(link)
        window.URL.revokeObjectURL(url)
        ElMessage.success('导出成功')
    } catch (error) {
        console.error('导出失败:', error)
        ElMessage.error('导出失败')
    } finally {
        state.loading = false
    }
};
posted @ 2024-11-21 09:41  idealy233  阅读(48)  评论(0编辑  收藏  举报