You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django存储文件删除功能在IIS失效,本地运行正常

问题

我开发了一个用于删除用户选定文件的Django模块,在确认用户的删除意愿后,编写了如下views.py代码:

@login_required(login_url='/login/')
def Delete_files(request, pk):
    # Get the RadioFile object based on the primary key (pk)
    radio_file = get_object_or_404(RadioFile, pk=pk)
    print(radio_file)
    # get the file path and file object from the database
    file_obj = RadioFile.objects.get(id=pk).audio_file    
    radio = radio_file.audio_file
    file_path = file_obj.path    
    print(file_path)    

    # Check that the user is the owner of the file    
    if request.user != radio_file.uploaded_by:          
        messages.success(request, 'File can be deleted by its owner.') # store the message in a message queue
        return redirect('/')
    elif os.path.exists(file_path) and not os.path.isfile(file_path):
        print(f"Error: {file_path} is not a file")
        response_data = {'success': False, 'error': str(e)}     
    else:
        try :
            with transaction.atomic():
                # Remove the many-to-many relationship with categories
                radio_file.categories.clear()
                radio_file.share_with.clear()

                # Delete the Radio object
                radio_file.delete()

                # Delete the file from the filesystem
                radio.close()
                radio.delete()
                
                messages.success(request, 'Radio and file deleted successfully.')
                response_data = {'success': True}
        except Exception as e:
                print(str(e))
                messages.error(request, 'some error is coming while deleteing file.')
        # Redirect to the file list view        
        return redirect('/')

上述代码在本地环境运行时可正常删除文件,但部署到IIS服务器时出现Win32权限错误,提示文件已被其他程序占用,而该文件仅被Python用于向用户展示文件列表。请协助排查并解决该问题。

排查与解决方案

1. 修复重复查询导致的未关闭文件句柄

代码中重复查询RadioFile对象(get_object_or_404后又调用RadioFile.objects.get),会生成多个文件实例,每个实例都可能持有未释放的文件句柄。Windows系统对文件句柄的锁定机制比Linux严格,未关闭的句柄会导致文件无法删除。

修改文件路径获取逻辑,去掉重复查询,仅使用已获取的radio_file对象:

# 替换原文件路径获取代码,避免持有多余的文件对象
file_path = radio_file.audio_file.path

2. 调整事务与文件删除的顺序

当前在事务块内先删除数据库对象再删除文件,事务未提交时,Django可能仍持有文件句柄。Windows下数据库对象未被完全垃圾回收时,句柄不会释放,导致删除失败。

将文件删除操作移出事务块,确保数据库记录删除完成后再处理文件:

try :
    with transaction.atomic():
        radio_file.categories.clear()
        radio_file.share_with.clear()
        # 先提交数据库删除操作
        radio_file.delete()
    
    # 事务提交后,确认文件存在再删除
    if os.path.exists(file_path):
        # 显式打开并关闭文件,强制释放可能存在的句柄
        with open(file_path, 'rb'):
            pass
        os.remove(file_path)
    
    messages.success(request, 'Radio and file deleted successfully.')
except Exception as e:
    print(str(e))
    messages.error(request, '删除文件时发生错误。')
return redirect('/')

3. 检查IIS应用池权限与缓存

  • 权限配置:确保IIS应用池的运行账户(如IIS AppPool\你的应用池名称)对文件存储目录拥有读取、写入、删除权限。Windows下需直接给应用池账户分配权限,不要依赖继承。
  • 禁用静态文件缓存:如果文件通过静态URL访问,IIS的静态文件模块可能缓存文件句柄。在项目根目录的Web.config中添加以下配置,禁用目标目录的缓存:
<location path="音频文件存储目录">
    <system.webServer>
        <staticContent>
            <clientCache cacheControlMode="DisableCache" />
        </staticContent>
    </system.webServer>
</location>

4. 替换Django的File.delete()方法

Django的FileField.delete()在Windows环境下可能存在句柄泄漏问题,建议直接使用Python标准库的os.remove()删除文件,确保所有句柄已释放后再执行删除操作。

内容的提问来源于stack exchange,提问作者PTB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 01:42:53